## vim:ts=4:et:nowrap
##
##---------------------------------------------------------------------------##
##
## PySol -- a Python Solitaire game
##
## Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
## Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
## Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
## Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
## Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
## Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
## All Rights Reserved.
##
## 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 2 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; see the file COPYING.
## If not, write to the Free Software Foundation, Inc.,
## 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
##
## Markus F.X.J. Oberhumer
## <markus@oberhumer.com>
## http://www.oberhumer.com/pysol
##
##---------------------------------------------------------------------------##


# imports
import os, sys, string, types, Tkinter

# PySol imports
if __name__ == "__main__":                                          #bundle#
    import pysoltk                                                  #bundle#
from mfxtools import ustr
from mfxutil import destruct
from util import IMAGE_EXTENSIONS
from actions import PysolToolbarActions

# Toolkit imports
from tkconst import tkversion, TK_DASH_PATCH
from tkconst import EVENT_HANDLED, EVENT_PROPAGATE
from tkwidget import MfxTooltip


# /***********************************************************************
# // A canvas that supports hiding.
# //
# // Note: Applications should call show/hide after constructor.
# ************************************************************************/

class _MfxToolbar:
    def __init__(self, top, relief=1):
        relief = 1
        self.top = top
        self.button_bg = None
        self.__setRelief(relief)
        self.side = -1
        self._tooltips = []
        self._widgets = []
        self._icon_height = 0
        # We must create a Canvas and a Frame with these parameters
        # in order to be able to hide the toolbar.
        self.canvas = Tkinter.Canvas(self.top, bd=0, highlightthickness=0)
        self.frame = Tkinter.Frame(self.canvas, bd=0, highlightthickness=1)
        self._initFrame()
        self.canvas.pack(side=Tkinter.TOP, fill=Tkinter.X)

    def __setRelief(self, relief):
        if type(relief) is types.IntType:
            relief = (Tkinter.RAISED, Tkinter.FLAT)[relief]
        elif relief in (Tkinter.RAISED, Tkinter.FLAT):
            pass
        else:
            relief = Tkinter.FLAT
        self.button_relief = relief
        if relief == Tkinter.RAISED:
            self.separator_relief = Tkinter.FLAT
        else:
            self.separator_relief = Tkinter.RAISED
        return relief

    # subclass overrideable
    def _initFrame(self):
        self.frame.pack(side=Tkinter.TOP, fill=Tkinter.X)

    # util
    def _createSeparator(self, width=12, side=Tkinter.LEFT, relief=None):
        if relief is None: relief = self.separator_relief
        if relief == Tkinter.FLAT or width <= 6:
            sep = Tkinter.Frame(self.frame, highlightthickness=0,
                                width=width, height=0, takefocus=0,
                                relief=relief)
            padx = 0
        else:
            height = max((self._icon_height or 38) - 4, 20)
            sep = Tkinter.Frame(self.frame, bd=1, highlightthickness=1,
                                width=4, height=height, takefocus=0,
                                relief=relief)
            padx = (width - 4) / 2
        sep.pack(side=side, padx=padx)
        self._widgets.append(sep)


    #
    # public methods
    #

    def show(self, side=1, resize=1):
        if self.side == side:
            return 0
        if resize:
            self.top.wm_geometry("")    # cancel user-specified geometry
        if not side:
            # hide
            if 0 and TK_DASH_PATCH:
                ### hmm, this doesn't work
                self.canvas.config(state="hidden")
            else:
                self.canvas.pack_propagate(0)
                self.canvas.config(height=0)
        else:
            # show
            if 0 and TK_DASH_PATCH:
                self.canvas.config(state="normal")
            else:
                self.canvas.pack_propagate(1)
            s = (None, Tkinter.TOP, Tkinter.BOTTOM)[side]
            self.canvas.pack(side=s, fill=Tkinter.X)
        self.side = side
        return 1

    def hide(self, resize=1):
        self.show(0, resize)

    def getSide(self):
        return self.side

    def destroy(self):
        for w in self._tooltips:
            if w: w.destroy()
        self._tooltips = []
        for w in self._widgets:
            if w: w.destroy()
        self._widgets = []

    def setCursor(self, cursor):
        if self.side:
            self.frame.config(cursor=cursor)
            self.frame.update_idletasks()


# /***********************************************************************
# //
# ************************************************************************/

class PysolToolbar(_MfxToolbar, PysolToolbarActions):
    def __init__(self, top, dir, size, relief=1):
        _MfxToolbar.__init__(self, top, relief)
        PysolToolbarActions.__init__(self)
        self.dir = dir
        self.size = size
        self._createButton("new",     self.mNewGame, tooltip="New game")
        self._createButton("restart", self.mRestart, tooltip="Restart the \ncurrent game")
        self._createSeparator()
        self._createButton("open",    self.mOpen   , tooltip="Open a \nsaved game")
        self._createButton("save",    self.mSave,    tooltip="Save game")
        self._createSeparator()
        self._createButton("undo",    self.mUndo,    tooltip="Undo last move")
        self._createButton("redo",    self.mRedo,    tooltip="Redo last move")
        self._createButton("autodrop", self.mDrop,   tooltip="Auto drop cards")
        self._createSeparator()
        self._createButton("stats",   self.mPlayerStats,  tooltip="View statistics")
        self._createButton("rules",   self.mHelpRules, tooltip="Rules for this game")
        self._createSeparator()
        self._createButton("quit",    self.mQuit,     tooltip="Quit PySol")
        self._createSeparator(width=20, relief=Tkinter.FLAT)
        ##self._createLabel("moves", padx=8, tooltip="Number of moves\nin this game")
        self._createLabel("player",  padx=8, tooltip="Player options")
        self.player_label.bind("<1>",self.mOptPlayerOptions)
        ##self.player_label.bind("<3>",self.mOptPlayerOptions)
        self.popup = None
        self.frame.bind("<1>", self.clickHandler)
        self.frame.bind("<3>", self.rightclickHandler)

    # Change the look of the frame to match the platform look
    def _initFrame(self):
        if 0 or os.name == "nt":
            self.frame.config(bd=1, relief=Tkinter.SOLID)
            self.frame.pack(side=Tkinter.TOP, fill=Tkinter.X, ipady=4)
            self._createSeparator(width=4, side=Tkinter.LEFT, relief=Tkinter.FLAT)
            self._createSeparator(width=4, side=Tkinter.RIGHT, relief=Tkinter.FLAT)
        else:
            self.frame.pack(side=Tkinter.TOP, fill=Tkinter.X, ipady=1)

    def _loadImage(self, name):
        file = os.path.join(self.dir, name)
        image = None
        for ext in IMAGE_EXTENSIONS:
            file = os.path.join(self.dir, name+ext)
            if os.path.isfile(file):
                image = Tkinter.PhotoImage(file=file)
                break
        return image

    def _createButton(self, name, command, padx=0, tooltip=None):
        image = self._loadImage(name)
        button = Tkinter.Button(self.frame, command=command, takefocus=0,
                                relief=self.button_relief)
        button.toolbar_name = name
        if image:
            button.config(image=image)
            if self._icon_height == 0:
                self._icon_height = image.height()
        if self.button_relief == Tkinter.FLAT:
            if self.button_bg is None:
                self.button_bg = self._getButtonBg(button["activebackground"])
                ##print self.button_bg
            button["activebackground"] = self.button_bg
        button.pack(side=Tkinter.LEFT, padx=padx)
        setattr(self, name + "_image", image)
        setattr(self, name + "_button", button)
        self._widgets.append(button)
        if tooltip:
            b = MfxTooltip(button)
            self._tooltips.append(b)
            b.setText(tooltip)

    def _getButtonBg(self, col):
        if type(col) is not types.StringType or col[0] != "#" or len(col) != 7:
            return "#f0f0f0"
        c = "#"
        for i in (1, 3, 5):
            v = string.atoi(col[i:i+2], 16)
            v = int(v + 24)
            if (v > 255): v = 255
            c = c + ("%02x" % v)
        return c

    def _createLabel(self, name, padx=0, side=Tkinter.RIGHT, tooltip=None):
        aspect = (400, 300) [self.size != 0]
        label = Tkinter.Message(self.frame, relief="ridge", justify="center", aspect=aspect)
        label.pack(side=side, padx=padx)
        setattr(self, name + "_label", label)
        self._widgets.append(label)
        if tooltip:
            b = MfxTooltip(label)
            self._tooltips.append(b)
            b.setText(tooltip)

    def _busy(self):
        if not self.side or not self.game or not self.menubar:
            return 1
        if self.game.demo:
            self.game.stopDemo()
        return self.game.busy


    #
    # public methods
    #

    def connectGame(self, game, menubar):
        PysolToolbarActions.connectGame(self, game, menubar)
        if self.popup:
            self.popup.destroy()
            destruct(self.popup)
            self.popup = None
        if menubar:
            tkopt = menubar.tkopt
            self.popup = Tkinter.Menu(self.canvas, tearoff=0)
            self.popup.add_command(label="Toolbar", state=Tkinter.DISABLED)
            self.popup.add_radiobutton(label="Hide", variable=tkopt.toolbar, value=0, command=menubar.mOptToolbar, underline=0)
            self.popup.add_radiobutton(label="Top", variable=tkopt.toolbar, value=1, command=menubar.mOptToolbar, underline=0)
            self.popup.add_radiobutton(label="Bottom", variable=tkopt.toolbar, value=2, command=menubar.mOptToolbar, underline=0)
            if 1:
                self.popup.add_separator()
                self.popup.add_radiobutton(label="Small icons", variable=tkopt.toolbar_size, value=0, command=menubar.mOptToolbarSize, underline=0)
                self.popup.add_radiobutton(label="Large icons", variable=tkopt.toolbar_size, value=1, command=menubar.mOptToolbarSize, underline=0)
            if 0:
                self.popup.add_separator()
                self.popup.add_radiobutton(label="Raised", variable=tkopt.toolbar_relief, value=0, command=menubar.mOptToolbarRelief, underline=0)
                self.popup.add_radiobutton(label="Flat", variable=tkopt.toolbar_relief, value=1, command=menubar.mOptToolbarRelief, underline=0)


    def setRelief(self, relief):
        pass    # FIXME


    def updateText(self, **kw):
        for name in kw.keys():
            label = getattr(self, name + "_label")
            label["text"] = ustr(kw[name])

    def updateImages(self, dir, size):
        if dir == self.dir and size == self.size:
            return 0
        if not os.path.isdir(dir):
            return 0
        old_dir, old_size = self.dir, self.size
        self.dir, self.size = dir, size
        data = []
        try:
            l = self.player_label
            for w in self._widgets:
                if not isinstance(w, Tkinter.Button):
                    continue
                name = w.toolbar_name
                image = self._loadImage(name)
                data.append((name, w, image))
        except:
            self.dir, self.size = old_dir, old_size
            return 0
        aspect = (400, 300) [size != 0]
        l.config(aspect=aspect)
        for name, w, image in data:
            w.config(image=image)
            setattr(self, name + "_image", image)
        return 1

    #
    # Mouse event handlers
    #

    def clickHandler(self, event):
        if self._busy(): return EVENT_HANDLED
        return EVENT_HANDLED

    def rightclickHandler(self, event):
        if self._busy(): return EVENT_HANDLED
        if self.popup:
            ##print event.x, event.y, event.x_root, event.y_root, event.__dict__
            self.popup.tk_popup(event.x_root, event.y_root)
        return EVENT_HANDLED

    def middleclickHandler(self, event):
        if self._busy(): return EVENT_HANDLED
        if 1 <= self.side <= 2:
            self.menubar.setToolbarSide(3 - self.side)
        return EVENT_HANDLED


# /***********************************************************************
# //
# ************************************************************************/


class TestToolbar(PysolToolbar):
    def __init__(self, top, args):
        dir = "large"
        if len(args) > 1: dir = args[1]
        dir = os.path.join(os.pardir, os.pardir, "data", "toolbar", dir)
        relief = 1
        relief = 0
        PysolToolbar.__init__(self, top, dir=dir, size=1, relief=relief)
        # test some settings
        self.updateText(player="Player\nPySol")
        self.undo_button["state"] = Tkinter.DISABLED
    def mQuit(self, *args):
        self.top.after_idle(self.top.quit)

def toolbar_main(args):
    tk = Tkinter.Tk()
    toolbar = TestToolbar(tk, args)
    toolbar.show()
    tk.mainloop()
    return 0

if __name__ == "__main__":
    sys.exit(toolbar_main(sys.argv))


