
"""
Sample basic GUI app demo that invokes Image2PyFile.PY

Passee on command line args to Image2PyFile.PY and display the results in a simple GUI.
Mesages that are progress, actions, warnings and notes are shown in the left pane.
Failure and error messages are shown on the right.

Ray Pasco
pascor(at)verizon(dot)net

Version
    1.2.1   2012-04-29  The error textCtrl is now located underneath the stdout textCtrl.
    1.2     2012-04-26  Fixed bugs, added -Q, enable all messages option.

"""

import sys, os
import wx

import Image2PyFile as i2p

#------------------------------------------------------------------------------

class RedirectOutput() :
    """
    Redirect print and write output to any control implementing method WriteText.
    
    Usage:
        stdoutTc = wx.TextCtrl( tcParent )
        
        sysStdoutSave = sys.stdout
        redirStd = RedirectOutput( stdoutTc )
        sys.stdout = redirStd
        
        ...
        
        # Undo the output redirection, if desired.
        sys.stdout = sysStdoutSave
    """
    
    # Created : Mike Driscoll 
    # Contact : mike@pythonlibrary.org
    # Website : ???

    def __init__( self, textDisplayControl ) :
        self.textOutWidget = textDisplayControl

    def write( self, s ) :
        self.textOutWidget.WriteText( s )
    
#end RedirectOutput class

DEBUG_REDIRECT_OUTPUT_TO_SHELL = 0

#------------------------------------------------------------------------------
#===============================================================================
#------------------------------------------------------------------------------

class AppFrame( wx.Frame ) :
 
    def __init__( self, args ) :
        DEBUG = 0
        
        wx.Frame.__init__( self, None, wx.ID_ANY, title='Image2PyFile GUI Demo' )
        self.SetClientSize( (750, 300) )
        self.SetPosition( (100, 0) )
    
        # Add a panel so the Frame looks and acts the same on all platforms.
        frmPanel = wx.Panel( self, -1 )
        
        # This implements an alternate very easy way to exist this app.
        frmPanel.Bind( wx.EVT_LEFT_DCLICK, self.OnExit )
        
        #-----
        
        stdoutTc_vertSizer = wx.BoxSizer( wx.VERTICAL )
        
        stdoutTc_stTxt = wx.StaticText( frmPanel, -1, 'Successful Operations' )
        stdoutTc_vertSizer.Add( stdoutTc_stTxt, 0, wx.ALL|wx.EXPAND, 5 )
        
        sharedTcStyle = wx.TE_MULTILINE|wx.TE_READONLY|wx.VSCROLL|wx.HSCROLL| wx.TE_RICH2
        
        stdoutTc = wx.TextCtrl( frmPanel, wx.NewId(), style=sharedTcStyle )
        stdoutTc.Bind( wx.EVT_LEFT_DCLICK, self.OnExit )
        # Create a monospaced font from the default.
        self.SetMonospaceFont( stdoutTc )
        
        stdoutTc_vertSizer.Add( stdoutTc, 1, wx.ALL|wx.EXPAND, 5 )
        
        #-----
        
        stderrTc_vertSizer = wx.BoxSizer( wx.VERTICAL )
        
        stderrTc_stTxt = wx.StaticText( frmPanel, -1, 'Failed Operations' )
        stderrTc_vertSizer.Add( stderrTc_stTxt, 0, wx.ALL|wx.EXPAND, 5 )
        
        stderrTc = wx.TextCtrl( frmPanel, wx.NewId(), style=sharedTcStyle )
        stderrTc.Bind( wx.EVT_LEFT_DCLICK, self.OnExit )
        # Create a monospaced font from the default.
        self.SetMonospaceFont( stderrTc )
        
        stderrTc_vertSizer.Add( stderrTc, 1, wx.ALL|wx.EXPAND, 5 )
        
        # Exit Button
        exitBtn = wx.Button( frmPanel, wx.ID_ANY, 'Exit' )
        exitBtn.Bind( wx.EVT_BUTTON, self.OnExit)
        
        # An overall sizer for the Frame client contents
        frmPanel_vertSizer = wx.BoxSizer( wx.VERTICAL )
        
        frmPanel_vertSizer.Add( stdoutTc_vertSizer, 1, wx.ALL|wx.EXPAND, 5 )
        frmPanel_vertSizer.Add( stderrTc_vertSizer, 1, wx.ALL|wx.EXPAND, 5 )
        
        frmPanel_vertSizer.Add( exitBtn, 0, wx.CENTER, 5 )
        frmPanel_vertSizer.Add( (10, 10) )
        frmPanel.SetSizer( frmPanel_vertSizer )
        
        #-----
        
        if DEBUG_REDIRECT_OUTPUT_TO_SHELL :     # DEBUG
            
            pass    # All output will normally go into textCtrl's by default.
            
        else :      
            
            # Redirect all text output from Image2PyFile.py to the textCtrl's.
            stdoutOrig, stderrOrig = sys.stdout, sys.stderr
            
            sys.stdout = RedirectOutput( stdoutTc )
            sys.stderr = RedirectOutput( stderrTc )
            
        #end if
        
        #-----
        
        # Process the command line, process  and display the results.
        i2p.Image2PyFile( args )         # All output info text will appear in the GUI.
        
        stdoutTc.SetInsertionPoint( 0 )    # Move the cursor back to the first line.
        stderrTc.SetInsertionPoint( 0 )
        
        # Show the error/failure messages pane if there are any messages.
        if (stderrTc.GetNumberOfLines() > 1) :        # Value of 1 == no lines of text.
            
            stderrTc_vertSizer.ShowItems( True )      # Make the err panel controls appear.
            
            # Resize the Frame's client area to also show TextCtrl.
            clientSizeX, clientSizeY = self.GetClientSize()
            stdoutTcWid, stdoutTcHgt = stdoutTc_vertSizer.GetSize()
            # Make more room to display the error staticText and its textCtrl.
            self.SetClientSize( (clientSizeX, clientSizeY+275) )
        
        else :  # Err messages panel will not be visible if there was no output to stderr.
            stderrTc_vertSizer.ShowItems( False )  
        #end if
        frmPanel_vertSizer.Layout()
        
        self.Show()
        
    #end __init__
    
    #------------------------
    
    def OnExit( self, event ) :
        """A "hook" to allow future cleanup operations to be performed."""
        
        self.Destroy()
    
    #------------------------
    
    def SetMonospaceFont( self, ctrl ) :
        
        # Retrieve the current font so we can use maost of its characteristics.
        ctrlFont = ctrl.GetFont()
        
        # Args:   wx.Font( pointSize, family, style, weight, underline, face, encoding )
        
        # Set the horizontal size in pixels, NOT points ! Vert size is about 11 pixels/char.
        fontSize = 9   
        if os.name == 'nt' :    # A more vertically compact font. Same horizontal spacing, though.
            ctrlFont = wx.Font( fontSize, wx.FONTFAMILY_MODERN, ctrlFont.GetStyle(), 
                                ctrlFont.GetWeight(), ctrlFont.GetUnderlined(), "Lucida Console" )
        else :
            ctrlFont = wx.Font( fontSize, wx.FONTFAMILY_MODERN, ctrlFont.GetStyle(), 
                                ctrlFont.GetWeight(), ctrlFont.GetUnderlined(), str(ctrlFont.GetEncoding()) )
        #end if
        ctrl.SetFont( ctrlFont )
        
    #end def
    
#end AppFrame class

#==============================================================================

if __name__ == '__main__' :
    
    args = sys.argv[ 1: ]
    
    myApp = wx.App( redirect=True )
    appFrame = AppFrame( args )
    myApp.MainLoop()
    
#end if
