## 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
##
##---------------------------------------------------------------------------##

__all__ = ['TclError',
           'MfxCheckMenuItem',
           'MfxRadioMenuItem',
           'StringVar',
           'MfxRoot']

# imports
import os, sys, time, types
from Tkinter import TclError
import Tile as Tkinter
from tkFont import Font

# PySol imports
from pysollib.mfxutil import destruct, Struct
from pysollib.settings import PACKAGE, VERSION, WIN_SYSTEM
from pysollib.macosx.appSupport import setupApp
from tkutil import after_idle, init_tile, wm_set_icon
from tkconst import EVENT_HANDLED, EVENT_PROPAGATE

# /***********************************************************************
# // menubar
# ************************************************************************/

class MfxCheckMenuItem(Tkinter.BooleanVar):
    def __init__(self, menubar, path=None):
        Tkinter.BooleanVar.__init__(self)
    def set(self, value):
        if not value or value == "false": value = 0
        ##print value, type(value)
        ##assert type(value) is types.IntType and 0 <= value <= 1
        Tkinter.BooleanVar.set(self, value)


class MfxRadioMenuItem(Tkinter.IntVar):
    def __init__(self, menubar, path=None):
        Tkinter.IntVar.__init__(self)
    def set(self, value):
        ##assert type(value) is types.IntType and 0 <= value
        Tkinter.IntVar.set(self, value)


## BooleanVar = Tkinter.BooleanVar
## IntVar = Tkinter.IntVar

StringVar = Tkinter.StringVar


# /***********************************************************************
# // Wrapper class for Tk.
# // Required so that a Game will get properly destroyed.
# ************************************************************************/

class MfxRoot(Tkinter.Tk):
    def __init__(self, **kw):
        apply(Tkinter.Tk.__init__, (self,), kw)
        self.app = None
        # for interruptible sleep
        #self.sleep_var = Tkinter.IntVar(self)
        #self.sleep_var.set(0)
        self.sleep_var = 0
        self.after_id = None
        ##self.bind('<ButtonPress>', self._sleepEvent, add=True)

    def connectApp(self, app):
        self.app = app

    def initToolkit(self, app, fg=None, bg=None, font=None):
        setupApp(app)
        sw, sh, sd = self.winfo_screenwidth(), self.winfo_screenheight(), self.winfo_screendepth()
        self.wm_group(self)
        self.wm_title(PACKAGE + ' ' + VERSION)
        self.wm_iconname(PACKAGE + ' ' + VERSION)
        if sw < 640 or sh < 480:
            self.wm_minsize(400, 300)
        else:
            self.wm_minsize(540, 380)
        ##self.self.wm_maxsize(9999, 9999) # unlimited
        self.wm_protocol('WM_DELETE_WINDOW', self.wmDeleteWindow)
        prog = sys.executable
        if prog and os.path.isfile(prog):
            argv0 = os.path.normpath(sys.argv[0])
            prog = os.path.abspath(prog)
            if os.path.isfile(argv0):
                wm_command = prog + " " + os.path.abspath(argv0)
                self.wm_command(wm_command)
        if 1:
            # set expected window size to assist the layout of the window manager
            self.config(width=min(800,sw-64), height=min(600,sh-64))
        try:
            wm_set_icon(self, app.dataloader.findIcon())
        except: pass

        # font
        if font:
            self.option_add('*font', font)
        elif WIN_SYSTEM == 'x11':
            self.option_add('*font', 'Helvetica 12', 50)
            font = self.option_get('font', '')
        try:
            f = Font(self, font)
        except:
            print >> sys.stderr, 'invalid font name:', font
            pass
        else:
            if font:
                fa = f.actual()
                app.opt.fonts['default'] = (fa['family'],
                                            fa['size'],
                                            fa['slant'],
                                            fa['weight'])
            else:
                app.opt.fonts['default'] = None

        # theme
        try:
            init_tile(app, self, app.opt.tile_theme)
        except TclError:
            raise
        except Exception, err:
            print >> sys.stderr, 'ERROR: set theme:', err
        ##self.option_add('*Toolbar.relief', 'groove')
        ##self.option_add('*Toolbar.relief', 'raised')
        ##self.option_add('*Toolbar.borderWidth', 1)
        ##self.option_add('*Toolbar.Button.Pad', 2)
        ##self.option_add('*Toolbar.Button.default', 'disabled')
        ##self.option_add('*Toolbar*takeFocus', 0)


    # sometimes an update() is needed under Windows, whereas
    # under Unix an update_idletasks() would be enough...
    def busyUpdate(self):
        game = None
        if self.app: game = self.app.game
        if not game:
            self.update()
        else:
            old_busy = game.busy
            game.busy = 1
            if game.canvas:
                game.canvas.update()
            self.update()
            game.busy = old_busy

    def mainquit(self):
        self.after_idle(self.quit)

    def screenshot(self, filename):
        ##print 'MfxRoot.screenshot not yet implemented'
        pass

    def setCursor(self, cursor):
        if 0:
            ## FIXME: this causes ugly resizes !
            Tkinter.Tk.config(self, cursor=cursor)
        elif 0:
            ## and this is even worse
            ##print self.children
            for v in self.children.values():
                v.config(cursor=cursor)
        else:
            pass

    #
    # sleep
    #

    def sleep(self, seconds):
        #time.sleep(seconds)
        self.after(int(seconds*1000))
        return
        print 'sleep', seconds
        timeout = int(seconds*1000)
        self.sleep_var = 0
        while timeout > 0:
            self.update()
            self.update_idletasks()
            if self.sleep_var:
                break
            self.after(100)
            timeout -= 100
        print 'finish sleep'
        return
        if self.after_id:
            self.after_cancel(self.after_id)
        self.after_id = self.after(int(seconds*1000), self._sleepEvent)
        self.sleep_var.set(1)
        self.update()
        self.wait_variable(self.sleep_var)
        if self.after_id:
            self.after_cancel(self.after_id)
            self.after_id = None
        print 'finish sleep'

    def _sleepEvent(self, *args):
        return
        print '_sleepEvent', args
        self.interruptSleep()
        return EVENT_PROPAGATE

    def interruptSleep(self):
        return
        print 'interruptSleep'
        self.update()
        self.update_idletasks()
        self.sleep_var = 1
        #self.sleep_var.set(0)
        #self.after_idle(self.sleep_var.set, 0)

    #
    #
    #

    def update(self):
        Tkinter.Tk.update(self)

    def wmDeleteWindow(self):
        if self.app and self.app.menubar:
            self.app.menubar.mQuit()
        else:
            ##self.after_idle(self.quit)
            pass