# This file is part of GNU Enterprise.
#
# GNU Enterprise is free software; you can redistribute it
# and/or modify it under the terms of the GNU GPublic
# License as published by the Free Software Foundation; either
# version 3, or (at your option) any later version.
#
# GNU Enterprise 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 program; see the file COPYING. If not,
# write to the Free Software Foundation, Inc., 59 Temple Place
# - Suite 330, Boston, MA 02111-1307, USA.
#
# Copyright 2000-2009 Free Software Foundation
#
# $Id: UIdriver.py 9956 2009-10-11 18:54:57Z reinhard $


import sys

from gnue.common.apps import i18n
from gnue.forms.uidrivers._base import Exceptions
from gnue.forms.uidrivers._base.UIdriver import GFUserInterfaceBase

try:
    import win32gui, win32con, afxres, win32ui
except ImportError:
    raise Exceptions.DriverNotSupported, \
        _("The GNUe-Forms Win32 driver requires PyWin32.")
from pywin.mfc import window

from gnue.common import events
from gnue.common.apps import GDebug
from gnue.common.apps import GConfig
from gnue.common.utils.TextUtils import lineWrap

from gnue.forms import VERSION
from gnue.forms.GFForm import *

from gnue.forms.uidrivers.win32.GFwin32App import *
#from gnue.forms.uidrivers.wx.UIWXSplashScreen import *
from gnue.forms.uidrivers.win32.widgets._base  import *
from gnue.forms.uidrivers.win32.common import textEncode, textDecode
from gnue.forms.uidrivers.win32 import dialogs


def OnWMVScroll(hwnd, msg, wparam, lparam, widget):
    return widget.OnWMVScroll(hwnd, msg, wparam, lparam)

def OnWMMenuselect(hwnd, msg, wparam, lparam, widget):
    return widget.OnWMMenuselect(hwnd, msg, wparam, lparam)

def OnWMNotify(hwnd, msg, wparam, lparam, widget):
    return widget.OnWMNotify(hwnd, msg, wparam, lparam)

def OnWMDestroy(hwnd, msg, wparam, lparam, widget):
    win32gui.DestroyWindow(hwnd)

def OnWMClose(hwnd, msg, wparam, lparam, widget):
    return widget.OnWMClose(hwnd, msg, wparam, lparam)

def OnWMSize(hwnd, msg, wparam, lparam, widget):
    return widget.OnWMSize(hwnd, msg, wparam, lparam)

def OnWMCommand(hwnd, msg, wparam, lparam, widget):
    return widget.OnWMCommand(hwnd, msg, wparam, lparam)

def OnWMDefault(hwnd, msg, wparam, lparam, widget):
    return win32gui.DefWindowProc(hwnd, msg, wparam, lparam)

#
# GFUserInterface
#
# The public interface to the User Interface
# All UIs must provide this class
#
class GFUserInterface(GFUserInterfaceBase):

    _message_map = { win32con.WM_VSCROLL    : OnWMVScroll,
                     win32con.WM_MENUSELECT : OnWMMenuselect,
                     win32con.WM_NOTIFY     : OnWMNotify,
                     win32con.WM_DESTROY    : OnWMDestroy,
                     win32con.WM_CLOSE      : OnWMClose,
                     win32con.WM_SIZE       : OnWMSize,
                     win32con.WM_COMMAND    : OnWMCommand }

    _wndclass = None
  
    # ---------------------------------------------------------------------------
    # Constructor
    # ---------------------------------------------------------------------------
  
    def __init__(self, eventHandler, name="Undefined", disableSplash=None,
            parentContainer=None, moduleName=None):
  
        GFUserInterfaceBase.__init__(self, eventHandler, name,
                disableSplash, parentContainer, moduleName)
        self.__splash = None
  
        self._IdToGFObj = {}
        self._IdToUIObj = {}

        self._win32app = get_win32_app()
        win32gui.InitCommonControls()

        try:
            icon = win32gui.LoadImage(0, sys.prefix+'\py.ico', win32con.IMAGE_ICON,
                                                0, 0, win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE)
        except:
            icon = win32gui.LoadIcon(0, win32con.IDI_APPLICATION)

        if not self._wndclass:
            # Register the "GNUeWindow" class.
            wc = win32gui.WNDCLASS()
            wc.lpszClassName = "GNUeWindow"
            wc.hCursor = win32gui.LoadCursor( 0, win32con.IDC_ARROW )
            wc.hIcon = icon
            wc.hbrBackground = win32con.COLOR_BTNSHADOW #win32con.COLOR_WINDOW
            wc.lpfnWndProc = self._wndproc
            self.__class__._wndclass = win32gui.RegisterClass(wc)

        #
        # SplashScreen
        #
#    if not self._disableSplash:
#      self.splash = UIWXSplashScreen()

        font_name = gConfigForms('faceName')
        if not font_name:
            # explicite boolean check forces generated report parameter dialog
            # to use ANSI_VAR_FONT (GConfig typecast initialization problem...)
            if gConfigForms ('fixedWidthFont') == True:
                fnt = win32con.ANSI_FIXED_FONT
            else:
                fnt = win32con.ANSI_VAR_FONT

            lf = win32gui.GetObject(win32gui.GetStockObject(fnt))
            font_name = lf.lfFaceName
      
        font_spec = {'name':font_name, 'height':int(gConfigForms('pointSize'))}
        self._font = win32ui.CreateFont(font_spec)


        # Create a dummy window used to compute sizes
        dummyWindow = window.Wnd(win32ui.CreateWnd())
        dc = dummyWindow.GetWindowDC()

        dc.SelectObject(self._font)
        metrics = dc.GetTextMetrics()
        maxWidth = metrics["tmAveCharWidth"]
        maxHeight = metrics["tmHeight"]
        maxDescent = metrics["tmDescent"]
        maxLeading = metrics["tmExternalLeading"]
    
        self.textWidth    = int(maxWidth+maxLeading)  # The pixel width of text inside a widget
        self.textWidth    = int(self.textWidth)
        self.textHeight   = int(maxHeight+maxDescent)  # The pixel height of text inside a widget
        self.widgetWidth  = self.textWidth             # The pixel width of a 1 char widget (for things like buttons)
        self.widgetHeight = self.textHeight + 4       # The pixel height of a 1 char widget (for things like buttons)
    
        font_spec = {'name':font_name, 'height':int(gConfigForms('pointSize')) or -1}
        self._font = win32ui.CreateFont(font_spec)
    
        dummyWindow.ReleaseDC(dc)


    def _wndproc(self, hwnd, msg, wparam, lparam):
        try:
            widget = self._win32app._HwndToTkObj[hwnd]
        except:
            return win32gui.DefWindowProc(hwnd, msg, wparam, lparam)
      
        OnWM = self._message_map.get(msg, OnWMDefault)
        return OnWM(hwnd, msg, wparam, lparam, widget)



    # mainLoop
    #
    # The primary loop of the user interface.  Called once the UI is
    # fully activated
    #
    def mainLoop(self):
        self._win32app.main_loop()


    # ---------------------------------------------------------------------------
    # Start an input dialog and return the data record or None if cancelled
    # ---------------------------------------------------------------------------

    def _getInput (self, title, fields, cancel = True):
  
        try:
            parent = self._win32app._MainWindowList[0].GetHwnd()
        except:
            parent = 0
        dialog = dialogs.InputDialog (parent, title, fields, cancel)
        dialog.DoModal ()
        return dialog.inputData
    

    # ---------------------------------------------------------------------------
    # Show a simple error message
    # ---------------------------------------------------------------------------

    def _ui_show_error_(self, message):

        win32gui.MessageBox(0, message, "GNU Enterprise",
                win32con.MB_TASKMODAL | win32con.MB_ICONERROR | win32con.MB_OK)


    # ---------------------------------------------------------------------------
    # Show an exception
    # ---------------------------------------------------------------------------

    def _ui_show_exception_(self, group, name, message, detail):
      
        try:
            parent = self._win32app._MainWindowList[0].GetHwnd()
        except:
            parent = 0
        dialog = dialogs.ExceptionDialog (parent, group, name, message, detail)
        dialog.DoModal ()


    # ---------------------------------------------------------------------------
    # Exit the application
    # ---------------------------------------------------------------------------

    def _ui_exit_(self):
        """
        Exit the application.
        """

        for child in self._children:
            self._win32app._MainWindowList.remove(child.mainWindow)
            child.mainWindow.Destroy()

        if len(self._win32app._MainWindowList) == 0:
            win32gui.PostQuitMessage(0) # Terminate the app.

        #~ for window in self._win32app._MainWindowList:
            #~ if isinstance(window, Win32Window):
                #~ window.Enable(1)
                #~ win32gui.SetActiveWindow(window.GetHwnd())
