Exemple #1
0
class MfxScrolledCanvas:
    def __init__(self, parent, hbar=True, vbar=True, propagate=False, **kw):
        kwdefault(kw, highlightthickness=0, bd=1, relief='sunken')
        self.parent = parent
        self.createFrame(kw)
        self.canvas = None
        self.hbar = None
        self.vbar = None
        self.hbar_show = False
        self.vbar_show = False
        self.createCanvas(kw)
        self.frame.grid_rowconfigure(0, weight=1)
        self.frame.grid_columnconfigure(0, weight=1)
        self.frame.grid_propagate(propagate)
        if hbar:
            self.createHbar()
            self.bindHbar()
        if vbar:
            self.createVbar()
            self.bindVbar()
        ###self.canvas.focus_set()

    #
    #
    #

    def destroy(self):
        self.unbind_all()
        self.canvas.destroy()
        self.frame.destroy()

    def pack(self, **kw):
        self.frame.pack(**kw)

    def grid(self, **kw):
        self.frame.grid(**kw)

    #
    #
    #

    def setTile(self, app, i, force=False):
        tile = app.tabletile_manager.get(i)
        if tile is None or tile.error:
            return False
        ##print i, tile
        if i == 0:
            assert tile.color
            assert tile.filename is None
        else:
            assert tile.color is None
            assert tile.filename
            assert tile.basename
        if not force:
            if (i == app.tabletile_index and
                tile.color == app.opt.colors['table']):
                return False
        #
        if not self.canvas.setTile(tile.filename, tile.stretch, tile.save_aspect):
            tile.error = True
            return False

        if i == 0:
            self.canvas.config(bg=tile.color)
            ##app.top.config(bg=tile.color)
        else:
            self.canvas.config(bg=app.top_bg)
            ##app.top.config(bg=app.top_bg)

        self.canvas.setTextColor(app.opt.colors['text'])

        return True

    #
    #
    #

    def unbind_all(self):
        unbind_destroy(self.hbar)
        unbind_destroy(self.vbar)
        unbind_destroy(self.canvas)
        unbind_destroy(self.frame)

    def createFrame(self, kw):
        width = kw.get("width")
        height = kw.get("height")
        self.frame = Tkinter.Frame(self.parent, width=width, height=height)
    def createCanvas(self, kw):
        bd = kw['bd']
        kw['bd'] = 0
        relief = kw['relief']
        del kw['relief']
        frame = Tkinter.Frame(self.frame, bd=bd, relief=relief)
        frame.grid(row=0, column=0, sticky="news")
        self.canvas = MfxCanvas(frame, **kw)
        self.canvas.pack(expand=True, fill='both')
    def createHbar(self):
        self.hbar = Tkinter.Scrollbar(self.frame, takefocus=0,
                                      orient="horizontal")
        self.canvas["xscrollcommand"] = self._setHbar
        self.hbar["command"] = self.canvas.xview
        self.hbar.grid(row=1, column=0, sticky="we")
        self.hbar.grid_remove()
    def createVbar(self):
        self.vbar = Tkinter.Scrollbar(self.frame, takefocus=0)
        self.canvas["yscrollcommand"] = self._setVbar
        self.vbar["command"] = self.canvas.yview
        self.vbar.grid(row=0, column=1, sticky="ns")
        self.vbar.grid_remove()
    def bindHbar(self, w=None):
        if w is None:
            w = self.canvas
        bind(w, "<KeyPress-Left>", self.unit_left)
        bind(w, "<KeyPress-Right>", self.unit_right)
    def bindVbar(self, w=None):
        if w is None:
            w = self.canvas
        bind(w, "<KeyPress-Prior>", self.page_up)
        bind(w, "<KeyPress-Next>", self.page_down)
        bind(w, "<KeyPress-Up>", self.unit_up)
        bind(w, "<KeyPress-Down>", self.unit_down)
        bind(w, "<KeyPress-Begin>", self.scroll_top)
        bind(w, "<KeyPress-Home>", self.scroll_top)
        bind(w, "<KeyPress-End>", self.scroll_bottom)
        # mousewheel support
        if WIN_SYSTEM == 'x11':
            bind(w, '<4>', self.mouse_wheel_up)
            bind(w, '<5>', self.mouse_wheel_down)
        # don't work on Linux
        #bind(w, '<MouseWheel>', self.mouse_wheel)

    def mouse_wheel(self, *args):
        print 'MfxScrolledCanvas.mouse_wheel', args

    def _setHbar(self, first, last):
        if self.canvas.busy:
            return
        sb = self.hbar
        if float(first) <= 0 and float(last) >= 1:
            sb.grid_remove()
            self.hbar_show = False
        else:
            if self.canvas.winfo_ismapped():
                sb.grid()
                self.hbar_show = True
        sb.set(first, last)
    def _setVbar(self, first, last):
        if self.canvas.busy:
            return
        sb = self.vbar
        if float(first) <= 0 and float(last) >= 1:
            sb.grid_remove()
            self.vbar_show = False
        else:
            if self.canvas.winfo_ismapped():
                sb.grid()
                self.vbar_show = True
        sb.set(first, last)

    def _xview(self, *args):
        if self.hbar_show: self.canvas.xview(*args)
        return 'break'
    def _yview(self, *args):
        if self.vbar_show: self.canvas.yview(*args)
        return 'break'

    def page_up(self, *event):
        return self._yview('scroll', -1, 'page')
    def page_down(self, *event):
        return self._yview('scroll', 1, 'page')
    def unit_up(self, *event):
        return self._yview('scroll', -1, 'unit')
    def unit_down(self, *event):
        return self._yview('scroll', 1, 'unit')
    def mouse_wheel_up(self, *event):
        return self._yview('scroll', -5, 'unit')
    def mouse_wheel_down(self, *event):
        return self._yview('scroll', 5, 'unit')
    def page_left(self, *event):
        return self._xview('scroll', -1, 'page')
    def page_right(self, *event):
        return self._xview('scroll', 1, 'page')
    def unit_left(self, *event):
        return self._xview('scroll', -1, 'unit')
    def unit_right(self, *event):
        return self._xview('scroll', 1, 'unit')
    def scroll_top(self, *event):
        return self._yview('moveto', 0)
    def scroll_bottom(self, *event):
        return self._yview('moveto', 1)
class FindCardDialog(Tkinter.Toplevel):
    CARD_IMAGES = {} # key: (rank, suit)

    def __init__(self, parent, game, dir, size='large'):
        Tkinter.Toplevel.__init__(self)
        title = TITLE + ' - ' + _('Find card')
        self.title(title)
        self.wm_resizable(False, False)
        #
        ##self.images_dir = dir
        if size == 'large':
            self.images_dir = os.path.join(dir, 'large')
            self.label_width, self.label_height = LARGE_EMBLEMS_SIZE
        else:
            self.images_dir = os.path.join(dir, 'small')
            self.label_width, self.label_height = SMALL_EMBLEMS_SIZE
        self.canvas = MfxCanvas(self, bg='white')
        ##self.canvas = MfxCanvas(self, bg='black')
        self.canvas.pack(expand=True, fill='both')
        #
        self.groups = []
        self.highlight_items = None
        self.busy = False
        self.connectGame(game)
        #
        bind(self, "WM_DELETE_WINDOW", self.destroy)
        bind(self, "<Escape>", self.destroy)
        #
        ##self.normal_timeout = 400    # in milliseconds
        self.normal_timeout = int(1000*game.app.opt.timeouts['highlight_samerank'])
        self.hidden_timeout = 200
        self.timer = None

    def createCardLabel(self, suit, rank, x0, y0):
        dx, dy = self.label_width, self.label_height
        dir = self.images_dir
        canvas = self.canvas
        group = MfxCanvasGroup(canvas)
        #
        im = FindCardDialog.CARD_IMAGES.get((rank, suit))
        if im is None:
            r = '%02d' % (rank+1)
            s = 'cshd'[suit]
            fn = os.path.join(dir, r+s+'.gif')
            im = makeImage(file=fn)
            FindCardDialog.CARD_IMAGES[(rank, suit)] = im
        cim = MfxCanvasImage(canvas, x0, y0, image=im, anchor='nw')
        cim.addtag(group)
        cim.lower()
        #
        rect_width = 4
        x1, y1 = x0+dx, y0+dy
        rect = MfxCanvasRectangle(self.canvas, x0+1, y0+1, x1-1, y1-1,
                                  width=rect_width,
                                  fill=None,
                                  outline='red',
                                  state='hidden'
                                  )
        rect.addtag(group)
        #
        bind(group, '<Enter>',
             lambda e, suit=suit, rank=rank, rect=rect:
                 self.enterEvent(suit, rank, rect, group))
        bind(group, '<Leave>',
             lambda e, suit=suit, rank=rank, rect=rect:
                 self.leaveEvent(suit, rank, rect, group))
        self.groups.append(group)

    def connectGame(self, game):
        self.canvas.delete('all')
        self.game = game
        suits = game.gameinfo.suits
        ranks = game.gameinfo.ranks
        dx, dy = self.label_width, self.label_height
        uniq_suits = []
        i = 0
        for suit in suits:
            if suit in uniq_suits:
                continue
            uniq_suits.append(suit)
            j = 0
            for rank in ranks:
                x, y = dx*j+2, dy*i+2
                self.createCardLabel(suit=suit, rank=rank, x0=x, y0=y)
                j += 1
            i += 1
        w, h = dx*j+2, dy*i+2
        self.canvas.config(width=w, height=h)
        self.wm_iconname(TITLE + " - " + game.getTitleName())
        self.wm_geometry('')            # cancel user-specified geometry

    def enterEvent(self, suit, rank, rect, group):
        ##print 'enterEvent', suit, rank, self.busy
        if self.busy: return
        if self.game.demo: return
        self.busy = True
        self.highlight_items = self.game.highlightCard(suit, rank)
        if not self.highlight_items:
            self.highlight_items = []
        if self.highlight_items:
            self.timer = after(self, self.normal_timeout, self.timeoutEvent)
        rect.config(state='normal')
        self.canvas.update_idletasks()
        self.busy = False

    def leaveEvent(self, suit, rank, rect, group):
        ##print 'leaveEvent', suit, rank, self.busy
        if self.busy: return
        self.busy = True
        if self.highlight_items:
            for i in self.highlight_items:
                i.delete()
            self.highlight_items = []
        if self.timer:
            after_cancel(self.timer)
            self.timer = None
        rect.config(state='hidden')
        if self.game.canvas:
            self.game.canvas.update_idletasks()
        self.canvas.update_idletasks()
        self.busy = False


    def timeoutEvent(self, *event):
        if self.highlight_items:
            state = self.highlight_items[0].cget('state')
            if state in ('', 'normal'):
                state = 'hidden'
                self.timer = after(self, self.hidden_timeout,
                                   self.timeoutEvent)
            else:
                state = 'normal'
                self.timer = after(self, self.normal_timeout,
                                   self.timeoutEvent)
            for item in self.highlight_items:
                item.config(state=state)

    def destroy(self, *args):
        for l in self.groups:
            unbind_destroy(l)
        unbind_destroy(self)
        if self.timer:
            after_cancel(self.timer)
            self.timer = None
        self.wm_withdraw()
        if self.highlight_items:
            for i in self.highlight_items:
                i.delete()
        Tkinter.Toplevel.destroy(self)