#!/usr/bin/python

import sys

import wx

DEBUG = True
DEBUG = False   # Comment this line to see console info statements.

#------------------------------------------------------------------------------
###############################################################################
#------------------------------------------------------------------------------

class ParentControl( wx.Frame ) :
   
    def __init__( self ) :
        
        # Frame setup
        titleTxt = 'HatchedWinSizedUsingSLider'
        wx.Frame.__init__( self, None, -1, title=titleTxt, pos=(10, 20))
        self.SetClientSize( (400, 300) )
        self.Bind( wx.EVT_SIZE, self.OnSize )
        
        frmPanel = wx.Panel( self, -1)
        frmPanel.SetBackgroundColour( (200, 230, 240) )
        frmPanel.Bind( wx.EVT_LEFT_DCLICK, self.OnClose )
        
        self.CreateStatusBar()
        self.SetStatusText( titleTxt )
        
        #-----  Frame Contents
        
        # Create a container in which to place the hatched window.
        self.hwPanel = wx.Panel( frmPanel )
        self.hwPanel.SetBackgroundColour( (250, 240, 240) )
        self.hwPanel.Bind( wx.EVT_LEFT_DCLICK, self.OnClose )
        
        # Initial value, min value = 0, max value = 100
        # The BG color is the color of frmPanel
        self.horzSlider = wx.Slider( frmPanel, -1, 
            80, 0, 100, 
            (0, 0),                             # Using a sizer: position is ignored
            (self.GetClientSize()[0]-15, 50),   # size
            wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_LABELS )
        
        # Respond to changes in slider position.
        # This will cause the hatched window size to be changed.
        self.Bind( wx.EVT_SLIDER, self.OnSlider )
        self.sliderValue = self.horzSlider.GetValue()
        self.prevSliderValue = self.sliderValue
        
        #-----
        
        # Auto-manage size and placement of self.hwPanel and self.horzSlider
        self.frmPnl_vSzr = wx.BoxSizer( wx.VERTICAL )
        
        # This panel takes up all the frmPanel client area
        #   not claimed by the slider control.
        self.frmPnl_vSzr.Add( self.hwPanel, 1, wx.EXPAND )  # Expand along both major and minor axes
        self.frmPnl_vSzr.Add( self.horzSlider, 0, wx.EXPAND|wx.ALL, 5 ) # Keep fixed vert size
        frmPanel.SetSizer( self.frmPnl_vSzr )
        self.Layout()
        
        # Get the hatched window to initially show.
        # This also enables 
        self.frmPnl_vSzr.Fit( frmPanel)
        
        # The hatched window's size and position will be calculated 
        #   and set by CenterHatchedWinInHwPanel() defined below.
        # Auto-centering without resizing can't be accomplished by using sizers.
        # Both EVT_SIZE and EVT_SLIDER handlers call CenterHatchedWinInHwPanel().
        self.hatchedWin = HatchedWindow( self.hwPanel )
        
        #-----  For de-bug info
        
        self.OnSizeCtr  = 0      # For de-bug
        self.OnPaintCtr = 0      # For de-bug
        
    #end __init__
    
    #----------------------------------
    
    def RedrawImageWindow( self ) :
        """
        A hack that is very simple and works very well.
        """
    
        selfSizeX, selfSizeY = self.GetSize()

        # Marginally bump up, then back down the Frame size.
        self.SetSize( (selfSizeX+1, selfSizeY+1) )
        self.SetSize( (selfSizeX, selfSizeY) )
    
    #end def
    
    #----------------------------------
    
    def OnSize( self, event ) :
        """
        Define/redefine the position and size of the hatched window
        A wx.EVT_SIZE event generates a wx.EVT_PAINT event in objects 
        #   created from the class (instantiated from the class definition).
        
        Every wx.EVT_SIZE event generates a wx.EVT_PAINT event.
        This paint handler is just a pass-through.
        """
        
        # For de-bug
        self.OnSizeCtr += 1
        if DEBUG :
            print '-'*50
            print '----  ParentControl::OnSize()    self.OnSizeCtr ', self.OnSizeCtr
            print '                           self.GetClientSize() ', self.GetClientSize()
            print '                      self.hatchedWin.GetSize() ', self.hatchedWin.GetSize()
        #end if
        
        self.CenterHatchedWinInHwPanel()
        
        event.Skip()        # Necessary or even desireable ?
        
    #end def
    
    #----------------------------------
    
    def CenterHatchedWinInHwPanel( self ) :
        
        # The slider value [0..100] will set the hatched window size to [0..100%] 
        #   of each client axis containing self.hwPanel
        hwPanelWidth, hwPanelHeight = self.hwPanel.GetClientSize()
        
        # Resize hatchedWin
        newHwinWidth  = int( (self.sliderValue / 100.0) * hwPanelWidth  + 0.5)
        newHwinHeight = int( (self.sliderValue / 100.0) * hwPanelHeight + 0.5)
        newWinSize = (newHwinWidth, newHwinHeight)
        self.hatchedWin.SetSize( newWinSize )
        
        # Reposition hatchedWin
        newHwinPosX = (hwPanelWidth  - newHwinWidth)  / 2
        newHwinPosY = (hwPanelHeight - newHwinHeight) / 2
        newHwinPos = (newHwinPosX, newHwinPosY)
        self.hatchedWin.SetPosition ( newHwinPos )
        
        self.Layout()   # The sizer will resize and reposition its controls.
        
        self.hwPanel.Refresh( False )
        
    #end def
    
    #----------------------------------
    
    def OnPaint( self, event=None ) :
        """ STUB """
        
        if DEBUG :
            self.OnPaintCtr += 1
            print 'STUB  ParentControl::OnPaint()', self.OnPaintCtr;  print
        
        event.Skip()
        
    #end OnPaint def
        
    #----------------------------------
    
    def OnSlider( self, event ):
        """ 
        The slider value [0..100] will redefine the hatched window size
        to [0..100%] of the dimensions of the self.hwPanel client dimensions.
        """
        if DEBUG :
            print '----  OnSlider():'
        
        self.sliderValue = self.horzSlider.GetValue()
        if (self.sliderValue != self.prevSliderValue) :
            
            statStr = 'Slider @ %3d' % (self.sliderValue)
            self.SetStatusText( statStr )
            
            if DEBUG :
                print '            Current, Previous Slider Value',  \
                      self.sliderValue, self.prevSliderValue
            
            self.SendSizeEvent()
            
            self.prevSliderValue = self.sliderValue
            
            self.RedrawImageWindow()
            
        #end if
        
    #end OnSlider def
    
    #----------------------------------
    
    def OnClose( self, event ) :
        
        if DEBUG :
            print '----  ParentControl::OnClose()'
            
        self.Destroy()      # Exit app.MainLoop()
        
    #end def

#end ParentControl class

#------------------------------------------------------------------------------
###############################################################################
#------------------------------------------------------------------------------

class HatchedWindow( wx.Window ) :
    
    def __init__( self, parent ) :
        
        wx.Window.__init__( self, parent, -1 )
        self.Bind( wx.EVT_LEFT_DCLICK, self.OnClose )
        self.SetBackgroundColour( 'WHitE' )
        self.Bind( wx.EVT_PAINT, self.OnPaint )
        self.Bind( wx.EVT_SIZE,  self.OnSize )
        
        #-----
        
        self.OnPaintCtr = 0      # For de-bug console messages
        self.OnSizeCtr  = 0      # For de-bug
        
    #end __init__
    
    #----------------------------------
    
    def OnSize( self, event=None ) :
        """ STUB """
        
        if DEBUG :
            self.OnSizeCtr += 1
            print 'STUB  HatchedWindow::OnSize()', self.OnSizeCtr
            print
        
        event.Skip()
        
    #end def
    
    #----------------------------------
    
    def OnPaint( self, event=None ) :
        
        if DEBUG :
            self.OnPaintCtr += 1
            print '----  HatchedWindow::OnPaint()', self.OnPaintCtr
            print '-'*50
        
        dc = wx.PaintDC( self )
        
        # Define the background pattern.
        hatchColor = (0, 75, 0)                 # dark green
        dc.SetPen( wx.Pen( hatchColor, 1 ) )    # See wx.Brush() styles
        dc.SetBrush( wx.Brush( hatchColor, wx.BDIAGONAL_HATCH ) )
        selfSizeX, selfSizeY = self.GetSize()
        dc.DrawRectangle( 0, 0, selfSizeX, selfSizeY )
        
        event.Skip()
        
    #end OnPaint def
        
    #----------------------------------
    
    def OnClose( self, event ) :
        
        if DEBUG :
            print 'STUB  ParentControl::OnClose()'
        wx.Exit()       # Exit app.MainLoop()
        
    #end def

#end PanelHatchedBG class

#------------------------------------------------------------------------------

def WhatsInstalled() :

    # What packages are installed ?
    import os, sys, platform
    print
    if os.name == 'nt' :
        print 'Windows  ', platform.win32_ver()[1]
    else :
        print 'Platform ', platform.system()
    #end if
    print 'Python   ', sys.version
    addon_pkgs = [ ('Wx Version', 'wx.VERSION_STRING'),
                   ('Wx Pltform', 'wx.PlatformInfo'), ]
    try :
        import Image        # Doesn't need to be installed.
        pilStr = 'PIL       '
        pilAddonStr = 'Image.VERSION'
        addon_pkgs.append( (pilStr      , pilAddonStr) )
    except :
        pass
    #end try
    for addonStr, attribute in addon_pkgs :
        try :
            print addonStr, eval( attribute )
        except NameError :
            print
        #end try
    #end for
    print
    
#end WhatsInstalled def

#==============================================================================

if __name__ == '__main__'  :
    
    WhatsInstalled()
    
    app = wx.App( redirect=False )
    
    appFrame = ParentControl()
    appFrame.Show()
    
    app.MainLoop()
        
#end if
