From 5d8b82cabe7f969a405247bf3431fc97bb0b5d89 Mon Sep 17 00:00:00 2001
From: Shlomi Fish <shlomif@shlomifish.org>
Date: Sun, 14 Feb 2016 16:14:30 +0200
Subject: [PATCH] Move {tk,tile}/{card,tkcanvas} to ui.tktile.

They were identical in both places.
---
 pysollib/pysoltk.py                       |   6 +-
 pysollib/tile/findcarddialog.py           |   2 +-
 pysollib/tile/selectcardset.py            |   2 +-
 pysollib/tile/tkwidget.py                 |   2 +-
 pysollib/tk/card.py                       | 250 --------------
 pysollib/tk/findcarddialog.py             |   2 +-
 pysollib/tk/selectcardset.py              |   2 +-
 pysollib/tk/tkcanvas.py                   | 403 ----------------------
 pysollib/tk/tkwidget.py                   |   2 +-
 pysollib/{tile => ui/tktile}/card.py      |   2 +-
 pysollib/{tile => ui/tktile}/tkcanvas.py  |   0
 scripts/gen_individual_importing_tests.py |   6 +-
 12 files changed, 11 insertions(+), 668 deletions(-)
 delete mode 100644 pysollib/tk/card.py
 delete mode 100644 pysollib/tk/tkcanvas.py
 rename pysollib/{tile => ui/tktile}/card.py (99%)
 rename pysollib/{tile => ui/tktile}/tkcanvas.py (100%)

diff --git a/pysollib/pysoltk.py b/pysollib/pysoltk.py
index 779f121e..99b42c0c 100644
--- a/pysollib/pysoltk.py
+++ b/pysollib/pysoltk.py
@@ -26,8 +26,9 @@ from pysollib.settings import TOOLKIT, USE_TILE
 if TOOLKIT == 'tk':
     from pysollib.ui.tktile.tkconst import *
     from pysollib.ui.tktile.tkutil import *
+    from pysollib.ui.tktile.card import *
+    from pysollib.ui.tktile.tkcanvas import *
     if USE_TILE:
-        from pysollib.tile.tkcanvas import *
         from pysollib.tile.tkwrap import *
         from pysollib.tile.tkwidget import *
         from pysollib.tile.tkhtml import *
@@ -45,11 +46,9 @@ if TOOLKIT == 'tk':
         from pysollib.tile.statusbar import *
         from pysollib.tile.progressbar import *
         from pysollib.tile.menubar import *
-        from pysollib.tile.card import *
         from pysollib.tile.selectcardset import *
         from pysollib.tile.selecttree import *
     else:
-        from pysollib.tk.tkcanvas import *
         from pysollib.tk.tkwrap import *
         from pysollib.tk.tkwidget import *
         from pysollib.tk.tkhtml import *
@@ -67,7 +66,6 @@ if TOOLKIT == 'tk':
         from pysollib.tk.statusbar import *
         from pysollib.tk.progressbar import *
         from pysollib.tk.menubar import *
-        from pysollib.tk.card import *
         from pysollib.tk.selectcardset import *
         from pysollib.tk.selecttree import *
 
diff --git a/pysollib/tile/findcarddialog.py b/pysollib/tile/findcarddialog.py
index 1ab75263..1b4b4dc1 100644
--- a/pysollib/tile/findcarddialog.py
+++ b/pysollib/tile/findcarddialog.py
@@ -34,7 +34,7 @@ from pysollib.mygettext import _, n_
 # Toolkit imports
 from pysollib.ui.tktile.tkutil import after, after_cancel
 from pysollib.ui.tktile.tkutil import bind, unbind_destroy, makeImage
-from tkcanvas import MfxCanvas, MfxCanvasGroup, MfxCanvasImage, MfxCanvasRectangle
+from pysollib.ui.tktile.tkcanvas import MfxCanvas, MfxCanvasGroup, MfxCanvasImage, MfxCanvasRectangle
 
 from pysollib.settings import TITLE
 
diff --git a/pysollib/tile/selectcardset.py b/pysollib/tile/selectcardset.py
index ec7d2482..b594ff5b 100644
--- a/pysollib/tile/selectcardset.py
+++ b/pysollib/tile/selectcardset.py
@@ -38,7 +38,7 @@ from pysollib.resource import CSI
 # Toolkit imports
 from pysollib.ui.tktile.tkutil import loadImage
 from tkwidget import MfxDialog, MfxScrolledCanvas, PysolScale
-from tkcanvas import MfxCanvasImage
+from pysollib.ui.tktile.tkcanvas import MfxCanvasImage
 from selecttree import SelectDialogTreeLeaf, SelectDialogTreeNode
 from selecttree import SelectDialogTreeData, SelectDialogTreeCanvas
 
diff --git a/pysollib/tile/tkwidget.py b/pysollib/tile/tkwidget.py
index e3097ef8..24493094 100644
--- a/pysollib/tile/tkwidget.py
+++ b/pysollib/tile/tkwidget.py
@@ -47,7 +47,7 @@ from pysollib.settings import WIN_SYSTEM
 from pysollib.ui.tktile.tkutil import after, after_cancel
 from pysollib.ui.tktile.tkutil import bind, unbind_destroy
 from pysollib.ui.tktile.tkutil import makeToplevel, setTransient
-from tkcanvas import MfxCanvas
+from pysollib.ui.tktile.tkcanvas import MfxCanvas
 
 
 # ************************************************************************
diff --git a/pysollib/tk/card.py b/pysollib/tk/card.py
deleted file mode 100644
index f63001e4..00000000
--- a/pysollib/tk/card.py
+++ /dev/null
@@ -1,250 +0,0 @@
-#!/usr/bin/env python
-# -*- mode: python; coding: utf-8; -*-
-##---------------------------------------------------------------------------##
-##
-## Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
-## Copyright (C) 2003 Mt. Hood Playing Card Co.
-## Copyright (C) 2005-2009 Skomoroh
-##
-## This program is free software: you can redistribute it and/or modify
-## it under the terms of the GNU General Public License as published by
-## the Free Software Foundation, either version 3 of the License, or
-## (at your option) any later version.
-##
-## This program is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-## GNU General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with this program.  If not, see <http://www.gnu.org/licenses/>.
-##
-##---------------------------------------------------------------------------##
-
-__all__ = ['Card']
-
-# imports
-
-# PySol imports
-from pysollib.acard import AbstractCard
-
-# Toolkit imports
-from tkcanvas import MfxCanvasGroup, MfxCanvasImage
-
-
-# ************************************************************************
-# *
-# ************************************************************************
-
-class _HideableCard(AbstractCard):
-    def hide(self, stack):
-        if stack is self.hide_stack:
-            return
-        self.item.config(state="hidden")
-        self.hide_stack = stack
-        ##print "hide:", self.id, self.item.coords()
-
-    def unhide(self):
-        if self.hide_stack is None:
-            return 0
-        ##print "unhide:", self.id, self.item.coords()
-        self.item.config(state="normal")
-        self.hide_stack = None
-        return 1
-
-
-# ************************************************************************
-# * New implementation since 2.10
-# *
-# * We use a single CanvasImage and call CanvasImage.config() to
-# * turn the card.
-# * This makes turning cards a little bit slower, but dragging cards
-# * around is noticeable faster as the total number of images is
-# * reduced by half.
-# ************************************************************************
-
-class _OneImageCard(_HideableCard):
-    def __init__(self, id, deck, suit, rank, game, x=0, y=0):
-        _HideableCard.__init__(self, id, deck, suit, rank, game, x=x, y=y)
-        self._face_image = game.getCardFaceImage(deck, suit, rank)
-        self._back_image = game.getCardBackImage(deck, suit, rank)
-        self._shade_image = game.getCardShadeImage()
-        self._active_image = self._back_image
-        self.item = MfxCanvasImage(game.canvas, self.x, self.y, image=self._active_image, anchor="nw")
-        self.shade_item = None
-        ##self._setImage = self.item.config
-
-    def _setImage(self, image):
-        if image is not self._active_image:
-            self.item.config(image=image)
-            self._active_image = image
-
-    def showFace(self, unhide=1):
-        if not self.face_up:
-            self._setImage(image=self._face_image)
-            self.tkraise(unhide)
-            self.face_up = 1
-
-    def showBack(self, unhide=1):
-        if self.face_up:
-            self._setImage(image=self._back_image)
-            self.tkraise(unhide)
-            self.face_up = 0
-
-    def updateCardBackground(self, image):
-        self._back_image = image
-        if not self.face_up:
-            self._setImage(image=image)
-
-    #
-    # optimized by inlining
-    #
-
-    def moveBy(self, dx, dy):
-        dx, dy = int(dx), int(dy)
-        self.x = self.x + dx
-        self.y = self.y + dy
-        item = self.item
-        item.canvas.tk.call(item.canvas._w, "move", item.id, dx, dy)
-
-    # for resize
-    def update(self, id, deck, suit, rank, game):
-        self._face_image = game.getCardFaceImage(deck, suit, rank)
-        self._back_image = game.getCardBackImage(deck, suit, rank)
-        self._shade_image = game.getCardShadeImage()
-        if self.face_up:
-            img = self._face_image
-        else:
-            img = self._back_image
-        self.item.config(image=img)
-        self._active_image = img
-
-
-# ************************************************************************
-# * New idea since 3.00
-# *
-# * Hide a card by configuring the canvas image to None.
-# ************************************************************************
-
-class _OneImageCardWithHideByConfig(_OneImageCard):
-    def hide(self, stack):
-        if stack is self.hide_stack:
-            return
-        self._setImage(image=None)
-        self.hide_stack = stack
-
-    def unhide(self):
-        if self.hide_stack is None:
-            return 0
-        if self.face_up:
-            self._setImage(image=self._face_image)
-        else:
-            self._setImage(image=self._back_image)
-        self.hide_stack = None
-        return 1
-
-    #
-    # much like in _OneImageCard
-    #
-
-    def showFace(self, unhide=1):
-        if not self.face_up:
-            if unhide:
-                self._setImage(image=self._face_image)
-            self.item.tkraise()
-            self.face_up = 1
-
-    def showBack(self, unhide=1):
-        if self.face_up:
-            if unhide:
-                self._setImage(image=self._back_image)
-            self.item.tkraise()
-            self.face_up = 0
-
-    def updateCardBackground(self, image):
-        self._back_image = image
-        if not self.face_up and not self.hide_stack:
-            self._setImage(image=image)
-
-
-# ************************************************************************
-# * Old implementation prior to 2.10
-# *
-# * The card consists of two CanvasImages. To show the card face up,
-# * the face item is placed in front of the back. To show it face
-# * down, this is reversed.
-# ************************************************************************
-
-class _TwoImageCard(_HideableCard):
-    # Private instance variables:
-    #   __face, __back -- the canvas items making up the card
-    def __init__(self, id, deck, suit, rank, game, x=0, y=0):
-        _HideableCard.__init__(self, id, deck, suit, rank, game, x=x, y=y)
-        self.item = MfxCanvasGroup(game.canvas)
-        self.__face = MfxCanvasImage(game.canvas, self.x, self.y, image=game.getCardFaceImage(deck, suit, rank), anchor="nw")
-        self.__back = MfxCanvasImage(game.canvas, self.x, self.y, image=game.getCardBackImage(deck, suit, rank), anchor="nw")
-        self.__face.addtag(self.item)
-        self.__back.addtag(self.item)
-
-    def showFace(self, unhide=1):
-        if not self.face_up:
-            self.__face.tkraise()
-            self.tkraise(unhide)
-            self.face_up = 1
-
-    def showBack(self, unhide=1):
-        if self.face_up:
-            self.__back.tkraise()
-            self.tkraise(unhide)
-            self.face_up = 0
-
-    def updateCardBackground(self, image):
-        self.__back.config(image=image)
-
-
-# ************************************************************************
-# * New idea since 2.90
-# *
-# * The card consists of two CanvasImages. Instead of raising
-# * one image above the other we move the inactive image out
-# * of the visible canvas.
-# ************************************************************************
-
-class _TwoImageCardWithHideItem(_HideableCard):
-    # Private instance variables:
-    #   __face, __back -- the canvas items making up the card
-    def __init__(self, id, deck, suit, rank, game, x=0, y=0):
-        _HideableCard.__init__(self, id, deck, suit, rank, game, x=x, y=y)
-        self.item = MfxCanvasGroup(game.canvas)
-        self.__face = MfxCanvasImage(game.canvas, self.x, self.y + 11000, image=game.getCardFaceImage(deck, suit, rank), anchor="nw")
-        self.__back = MfxCanvasImage(game.canvas, self.x, self.y, image=game.getCardBackImage(deck, suit, rank), anchor="nw")
-        self.__face.addtag(self.item)
-        self.__back.addtag(self.item)
-
-    def showFace(self, unhide=1):
-        if not self.face_up:
-            self.__back.move(0, 10000)
-            ##self.__face.tkraise()
-            self.__face.move(0, -11000)
-            self.tkraise(unhide)
-            self.face_up = 1
-
-    def showBack(self, unhide=1):
-        if self.face_up:
-            self.__face.move(0, 11000)
-            ##self.__back.tkraise()
-            self.__back.move(0, -10000)
-            self.tkraise(unhide)
-            self.face_up = 0
-
-    def updateCardBackground(self, image):
-        self.__back.config(image=image)
-
-
-
-# choose the implementation
-Card = _TwoImageCardWithHideItem
-Card = _TwoImageCard
-Card = _OneImageCardWithHideByConfig
-Card = _OneImageCard
-
diff --git a/pysollib/tk/findcarddialog.py b/pysollib/tk/findcarddialog.py
index a8a14b7a..3bba685e 100644
--- a/pysollib/tk/findcarddialog.py
+++ b/pysollib/tk/findcarddialog.py
@@ -37,7 +37,7 @@ from pysollib.mygettext import _, n_
 # Toolkit imports
 from pysollib.ui.tktile.tkutil import after, after_cancel
 from pysollib.ui.tktile.tkutil import bind, unbind_destroy, makeImage
-from tkcanvas import MfxCanvas, MfxCanvasGroup, MfxCanvasImage, MfxCanvasRectangle
+from pysollib.ui.tktile.tkcanvas import MfxCanvas, MfxCanvasGroup, MfxCanvasImage, MfxCanvasRectangle
 
 from pysollib.settings import TITLE
 
diff --git a/pysollib/tk/selectcardset.py b/pysollib/tk/selectcardset.py
index 9a7172e3..fdd78eab 100644
--- a/pysollib/tk/selectcardset.py
+++ b/pysollib/tk/selectcardset.py
@@ -36,7 +36,7 @@ from pysollib.resource import CSI
 # Toolkit imports
 from pysollib.ui.tktile.tkutil import loadImage
 from tkwidget import MfxDialog, MfxScrolledCanvas
-from tkcanvas import MfxCanvasImage
+from pysollib.ui.tktile.tkcanvas import MfxCanvasImage
 from selecttree import SelectDialogTreeLeaf, SelectDialogTreeNode
 from selecttree import SelectDialogTreeData, SelectDialogTreeCanvas
 
diff --git a/pysollib/tk/tkcanvas.py b/pysollib/tk/tkcanvas.py
deleted file mode 100644
index 7912ed38..00000000
--- a/pysollib/tk/tkcanvas.py
+++ /dev/null
@@ -1,403 +0,0 @@
-#!/usr/bin/env python
-# -*- mode: python; coding: utf-8; -*-
-##---------------------------------------------------------------------------##
-##
-## Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
-## Copyright (C) 2003 Mt. Hood Playing Card Co.
-## Copyright (C) 2005-2009 Skomoroh
-##
-## This program is free software: you can redistribute it and/or modify
-## it under the terms of the GNU General Public License as published by
-## the Free Software Foundation, either version 3 of the License, or
-## (at your option) any later version.
-##
-## This program is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-## GNU General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with this program.  If not, see <http://www.gnu.org/licenses/>.
-##
-##---------------------------------------------------------------------------##
-
-__all__ = ['MfxCanvasGroup',
-           'MfxCanvasImage',
-           'MfxCanvasText',
-           'MfxCanvasLine',
-           'MfxCanvasRectangle',
-           'MfxCanvas']
-
-# imports
-import Tkinter, Canvas
-
-# PySol imports
-from pysollib.mfxutil import Image, ImageTk
-
-# Toolkit imports
-from pysollib.ui.tktile.tkutil import bind, unbind_destroy, loadImage
-
-
-# ************************************************************************
-# * canvas items
-# ************************************************************************
-
-class MfxCanvasGroup(Canvas.Group):
-    def __init__(self, canvas, tag=None):
-        Canvas.Group.__init__(self, canvas=canvas, tag=tag)
-        # register ourself so that we can unbind from the canvas
-        assert self.id not in self.canvas.items
-        self.canvas.items[self.id] = self
-    def addtag(self, tag, option="withtag"):
-        self.canvas.addtag(tag, option, self.id)
-    def delete(self):
-        del self.canvas.items[self.id]
-        Canvas.Group.delete(self)
-    def gettags(self):
-        return self.canvas.tk.splitlist(self._do("gettags"))
-
-class MfxCanvasImage(Canvas.ImageItem):
-    def __init__(self, canvas, x, y, **kwargs):
-        self.init_coord = x, y
-        group = None
-        if 'group' in kwargs:
-            group = kwargs['group']
-            del kwargs['group']
-        if 'image' in kwargs:
-            self._image = kwargs['image']
-        Canvas.ImageItem.__init__(self, canvas, x, y, **kwargs)
-        if group:
-            self.addtag(group)
-    def moveTo(self, x, y):
-        c = self.coords()
-        self.move(x - int(c[0]), y - int(c[1]))
-    def show(self):
-        self.config(state='normal')
-    def hide(self):
-        self.config(state='hidden')
-
-MfxCanvasLine = Canvas.Line
-
-class MfxCanvasRectangle(Canvas.Rectangle):
-    def __init__(self, canvas, *args, **kwargs):
-        group = None
-        if 'group' in kwargs:
-            group = kwargs['group']
-            del kwargs['group']
-        Canvas.Rectangle.__init__(self, canvas, *args, **kwargs)
-        if group:
-            self.addtag(group)
-
-class MfxCanvasText(Canvas.CanvasText):
-    def __init__(self, canvas, x, y, preview=-1, **kwargs):
-        self.init_coord = x, y
-        self.x, self.y = x, y
-        if preview < 0:
-            preview = canvas.preview
-        if preview > 1:
-            return
-        if "fill" not in kwargs:
-            kwargs["fill"] = canvas._text_color
-        group = None
-        if 'group' in kwargs:
-            group = kwargs['group']
-            del kwargs['group']
-        Canvas.CanvasText.__init__(self, canvas, x, y, **kwargs)
-        self.text_format = None
-        canvas._text_items.append(self)
-        if group:
-            self.addtag(group)
-    def moveTo(self, x, y):
-        dx, dy = x - self.x, y - self.y
-        self.x, self.y = x, y
-        self.move(dx, dy)
-
-
-# ************************************************************************
-# * canvas
-# ************************************************************************
-
-class MfxCanvas(Tkinter.Canvas):
-    def __init__(self, *args, **kw):
-        Tkinter.Canvas.__init__(self, *args, **kw)
-        self.preview = 0
-        self.busy = False
-        # this is also used by lib-tk/Canvas.py
-        self.items = {}
-        # private
-        self.__tileimage = None
-        self.__tiles = []           # id of canvas items
-        self.__topimage = None
-        self.__tops = []            # id of canvas items
-        # friend MfxCanvasText
-        self._text_color = "#000000"
-        self._stretch_bg_image = 0
-        self._save_aspect_bg_image = 0
-        self._text_items = []
-        #
-        self.xmargin, self.ymargin = 10, 10
-        # resize bg image
-        self.bind('<Configure>', self.setBackgroundImage)
-
-    def setBackgroundImage(self, event=None):
-        ##print 'setBackgroundImage', self._bg_img
-        if not hasattr(self, '_bg_img'):
-            return
-        if not self._bg_img: # solid color
-            return
-        stretch = self._stretch_bg_image
-        save_aspect = self._save_aspect_bg_image
-        if Image:
-            if stretch:
-                w, h = self._geometry()
-                if save_aspect:
-                    w0, h0 = self._bg_img.size
-                    a = min(float(w0)/w, float(h0)/h)
-                    w0, h0 = int(w0/a), int(h0/a)
-                    im = self._bg_img.resize((w0, h0))
-                else:
-                    im = self._bg_img.resize((w, h))
-                image = ImageTk.PhotoImage(im)
-            else:
-                image = ImageTk.PhotoImage(self._bg_img)
-        else: # not Image
-            stretch = 0
-            image = self._bg_img
-        for id in self.__tiles:
-            self.delete(id)
-        self.__tiles = []
-        # must keep a reference to the image, otherwise Python will
-        # garbage collect it...
-        self.__tileimage = image
-        if stretch:
-            #
-            if self.preview:
-                dx, dy = 0, 0
-            else:
-                dx, dy = -self.xmargin, -self.ymargin
-            id = self._x_create("image", dx, dy, image=image, anchor="nw")
-            self.tag_lower(id)          # also see tag_lower above
-            self.__tiles.append(id)
-        else:
-            iw, ih = image.width(), image.height()
-            sw, sh = self._geometry()
-            for x in range(-self.xmargin, sw, iw):
-                for y in range(-self.ymargin, sh, ih):
-                    id = self._x_create("image", x, y, image=image, anchor="nw")
-                    self.tag_lower(id)          # also see tag_lower above
-                    self.__tiles.append(id)
-        return 1
-
-    def _geometry(self):
-        w = max(self.winfo_width(), int(self.cget('width')))
-        h = max(self.winfo_height(), int(self.cget('height')))
-        scrollregion = self.cget('scrollregion')
-        if not scrollregion:
-            return w, h
-        x, y, sw, sh = [int(i) for i in scrollregion.split()]
-        sw -= x
-        sh -= y
-        w = max(w, sw)
-        h = max(h, sh)
-        return w, h
-
-
-    #
-    # top-image support
-    #
-
-    def _x_create(self, itemType, *args, **kw):
-        return Tkinter.Canvas._create(self, itemType, args, kw)
-
-    def _create(self, itemType, args, kw):
-        ##print "_create:", itemType, args, kw
-        id = Tkinter.Canvas._create(self, itemType, args, kw)
-        if self.__tops:
-            self.tk.call(self._w, "lower", id, self.__tops[0])
-        return id
-
-    def tag_raise(self, id, aboveThis=None):
-        ##print "tag_raise:", id, aboveThis
-        if aboveThis is None and self.__tops:
-            self.tk.call(self._w, "lower", id, self.__tops[0])
-        else:
-            self.tk.call(self._w, "raise", id, aboveThis)
-
-    def tag_lower(self, id, belowThis=None):
-        ##print "tag_lower:", id, belowThis
-        if belowThis is None and self.__tiles:
-            self.tk.call(self._w, "raise", id, self.__tiles[-1])
-        else:
-            self.tk.call(self._w, "lower", id, belowThis)
-
-
-    #
-    #
-    #
-
-    def setInitialSize(self, width, height, margins=True, scrollregion=True):
-        #print 'Canvas.setInitialSize:', width, height, scrollregion
-        if self.preview:
-            self.config(width=width, height=height,
-                        scrollregion=(0, 0, width, height))
-        else:
-            # add margins
-            dx, dy = self.xmargin, self.ymargin
-            if margins:
-                w, h = dx+width+dx, dy+height+dy
-            else:
-                w, h = width, height
-            self.config(width=w, height=h)
-            if scrollregion:
-                self.config(scrollregion=(-dx, -dy, width+dx, height+dy))
-            else:
-                # no scrolls
-                self.config(scrollregion=(-dx, -dy, dx, dy))
-
-
-    #
-    #
-    #
-
-    # delete all CanvasItems, but keep the background and top tiles
-    def deleteAllItems(self):
-        self._text_items = []
-        for id in self.items.keys():
-            assert id not in self.__tiles   # because the tile is created by id
-            unbind_destroy(self.items[id])
-            self.items[id].delete()
-        assert self.items == {}
-
-    def findCard(self, stack, event):
-        if isinstance(stack.cards[0].item, Canvas.Group):
-            current = self.gettags("current")           # get tags
-            for i in range(len(stack.cards)):
-                if stack.cards[i].item.tag in current:
-                    return i
-        else:
-##             current = self.find("withtag", "current")   # get item ids
-##             for i in range(len(stack.cards)):
-##                 if stack.cards[i].item.id in current:
-##                     return i
-            if self.preview:
-                dx, dy = 0, 0
-            else:
-                dx, dy = -self.xmargin, -self.ymargin
-            x = event.x+dx+self.xview()[0]*int(self.cget('width'))
-            y = event.y+dy+self.yview()[0]*int(self.cget('height'))
-            ##x, y = event.x, event.y
-            items = list(self.find_overlapping(x,y,x,y))
-            items.reverse()
-            for item in items:
-                for i in range(len(stack.cards)):
-                    if stack.cards[i].item.id == item:
-                        return i
-        return -1
-
-    def setTextColor(self, color):
-        if color is None:
-            c = self.cget("bg")
-            if not isinstance(c, str) or c[0] != "#" or len(c) != 7:
-                return
-            v = []
-            for i in (1, 3, 5):
-                v.append(int(c[i:i+2], 16))
-            luminance = (0.212671 * v[0] + 0.715160 * v[1] + 0.072169 * v[2]) / 255
-            ##print c, ":", v, "luminance", luminance
-            color = ("#000000", "#ffffff") [luminance < 0.3]
-        if self._text_color != color:
-            self._text_color = color
-            for item in self._text_items:
-                item.config(fill=self._text_color)
-
-    def setTile(self, image, stretch=0, save_aspect=0):
-        ##print 'setTile:', image, stretch
-        if image:
-            if Image:
-                try:
-                    self._bg_img = Image.open(image)
-                except:
-                    return 0
-            else:
-                try:
-                    self._bg_img = loadImage(file=image, dither=1)
-                except:
-                    return 0
-            self._stretch_bg_image = stretch
-            self._save_aspect_bg_image = save_aspect
-            self.setBackgroundImage()
-        else:
-            for id in self.__tiles:
-                self.delete(id)
-            self.__tiles = []
-            self._bg_img = None
-        return 1
-
-    def setTopImage(self, image, cw=0, ch=0):
-        try:
-            if image and isinstance(image, str):
-                image = loadImage(file=image)
-        except Tkinter.TclError:
-            return 0
-        if len(self.__tops) == 1 and image is self.__tops[0]:
-            return 1
-        for id in self.__tops:
-            self.delete(id)
-        self.__tops = []
-        # must keep a reference to the image, otherwise Python will
-        # garbage collect it...
-        self.__topimage = image
-        if image is None:
-            return 1
-        iw, ih = image.width(), image.height()
-        if cw <= 0:
-            ##cw = max(int(self.cget("width")), self.winfo_width())
-            cw = self.winfo_width()
-        if ch <= 0:
-            ##ch = max(int(self.cget("height")),  self.winfo_height())
-            ch = self.winfo_height()
-        ###print iw, ih, cw, ch
-        x = (cw-iw)/2-self.xmargin+self.xview()[0]*int(self.cget('width'))
-        y = (ch-ih)/2-self.ymargin+self.yview()[0]*int(self.cget('height'))
-        id = self._x_create("image", x, y, image=image, anchor="nw")
-        self.tk.call(self._w, "raise", id)
-        self.__tops.append(id)
-        return 1
-
-    #
-    # Pause support
-    #
-
-    def hideAllItems(self):
-        for item in self.items.values():
-            item.config(state='hidden')
-
-    def showAllItems(self):
-        for item in self.items.values():
-            item.config(state='normal')
-
-
-    #
-    # restricted but fast _bind and _substitute
-    #
-
-    def _bind(self, what, sequence, func, add, needcleanup=1):
-        funcid = self._register(func, self._substitute, needcleanup)
-        cmd = ('%sif {"[%s %s]" == "break"} break\n' %
-                (add and '+' or '', funcid, "%x %y"))
-        self.tk.call(what + (sequence, cmd))
-        return funcid
-
-    def _substitute(self, *args):
-        e = Tkinter.Event()
-        try:
-            # Tk changed behavior in 8.4.2, returning "??" rather more often.
-            e.x = int(args[0])
-        except ValueError:
-            e.x = args[0]
-        try:
-            e.y = int(args[1])
-        except ValueError:
-            e.y = args[1]
-        return (e,)
-
diff --git a/pysollib/tk/tkwidget.py b/pysollib/tk/tkwidget.py
index 6f27a1c0..ecf6aad9 100644
--- a/pysollib/tk/tkwidget.py
+++ b/pysollib/tk/tkwidget.py
@@ -46,7 +46,7 @@ from pysollib.settings import WIN_SYSTEM
 from pysollib.ui.tktile.tkutil import after, after_cancel
 from pysollib.ui.tktile.tkutil import bind, unbind_destroy
 from pysollib.ui.tktile.tkutil import makeToplevel, setTransient
-from tkcanvas import MfxCanvas
+from pysollib.ui.tktile.tkcanvas import MfxCanvas
 
 
 # ************************************************************************
diff --git a/pysollib/tile/card.py b/pysollib/ui/tktile/card.py
similarity index 99%
rename from pysollib/tile/card.py
rename to pysollib/ui/tktile/card.py
index f63001e4..5f8d1da7 100644
--- a/pysollib/tile/card.py
+++ b/pysollib/ui/tktile/card.py
@@ -29,7 +29,7 @@ __all__ = ['Card']
 from pysollib.acard import AbstractCard
 
 # Toolkit imports
-from tkcanvas import MfxCanvasGroup, MfxCanvasImage
+from pysollib.ui.tktile.tkcanvas import MfxCanvasGroup, MfxCanvasImage
 
 
 # ************************************************************************
diff --git a/pysollib/tile/tkcanvas.py b/pysollib/ui/tktile/tkcanvas.py
similarity index 100%
rename from pysollib/tile/tkcanvas.py
rename to pysollib/ui/tktile/tkcanvas.py
diff --git a/scripts/gen_individual_importing_tests.py b/scripts/gen_individual_importing_tests.py
index 56f1a5d0..67bf53c7 100644
--- a/scripts/gen_individual_importing_tests.py
+++ b/scripts/gen_individual_importing_tests.py
@@ -133,7 +133,6 @@ for module_name in [
 'pysollib.settings',
 'pysollib.stack',
 'pysollib.stats',
-'pysollib.tile.card',
 'pysollib.tile.colorsdialog',
 'pysollib.tile.edittextdialog',
 'pysollib.tile.findcarddialog',
@@ -150,7 +149,6 @@ for module_name in [
 'pysollib.tile.soundoptionsdialog',
 'pysollib.tile.statusbar',
 'pysollib.tile.timeoutsdialog',
-'pysollib.tile.tkcanvas',
 'pysollib.tile.tkhtml',
 'pysollib.tile.tkstats',
 'pysollib.tile.tktree',
@@ -159,7 +157,6 @@ for module_name in [
 'pysollib.tile.toolbar',
 'pysollib.tile.ttk',
 'pysollib.tile.wizarddialog',
-'pysollib.tk.card',
 'pysollib.tk.colorsdialog',
 'pysollib.tk.edittextdialog',
 'pysollib.tk.findcarddialog',
@@ -177,7 +174,6 @@ for module_name in [
 'pysollib.tk.statusbar',
 'pysollib.tk.tabpage',
 'pysollib.tk.timeoutsdialog',
-'pysollib.tk.tkcanvas',
 'pysollib.tk.tkhtml',
 'pysollib.tk.tkstats',
 'pysollib.tk.tktree',
@@ -185,7 +181,9 @@ for module_name in [
 'pysollib.tk.tkwrap',
 'pysollib.tk.toolbar',
 'pysollib.tk.wizarddialog',
+'pysollib.ui.tktile.card',
 'pysollib.ui.tktile.menubar',
+'pysollib.ui.tktile.tkcanvas',
 'pysollib.ui.tktile.tkconst',
 'pysollib.ui.tktile.tkutil',
 'pysollib.util',