#--(Python Source Browser Example)----------------------------------------------
"""
This lesson shows a combination of the **DirectoryEditor**, the 
**TabularEditor** and the **CodeEditor** used together to create a very simple 
Python source browser. In the **Demo** tab you can:

- Use the **DirectoryEditor** on the left to navigate to and select 
  directories containing Python source files.
- Use the **TabularEditor** on the top-right to view information about and 
  to select Python source files in the currently selected directory.
- View the currently selected Python source file's contents in the 
  **CodeEditor** in the bottom-right.
   
As an extra *feature*, the **TabularEditor** also displays a:
    
- Red ball if the file size > 64KB.
- Blue ball if the file size > 16KB.
 
As with the *Single and Married Person Example* tutorial, this example shows you 
how to:
    
- Set up a **TabularEditor**.
- Define a **TabularAdapter** subclass that meets the display requirements of
  the application.

In this example, please note the use of the *even_bg_color* trait in the
**FileInfoAdapter** adapter class to set up alternating line colors in the table
for improved readability.

Also note that the *name*, *size*, *time* and *date* columns define *column_id*
values which correspond directly with traits defined in the **FileInfo** class,
but the *big* column id is an artifical column defined to display the file size
related *blue ball* and *red ball* images when the file size exceeds various
thresholds. The column id is used simply to provide a name reference for the
related trait and property definitions in the adapter class itself.
"""

#--<Imports>--------------------------------------------------------------------

import enthought.traits
import enthought.traits.ui

import wx

from time \
    import localtime, strftime
    
from os \
    import listdir
    
from os.path \
    import getsize, getmtime, isfile, join, splitext, basename, dirname

from enthought.traits.api \
    import HasPrivateTraits, Str, Float, List, Directory, File, Code, \
           Instance, Property, cached_property
    
from enthought.traits.ui.api \
    import View, Item, HSplit, VSplit, TabularEditor
    
from enthought.traits.ui.tabular_adapter \
    import TabularAdapter

from enthought.pyface.image_resource \
    import ImageResource
    
#--<Constants>------------------------------------------------------------------

# Necessary because of the dynamic way in which the demos are loaded:
search_path = [ join( dirname( enthought.traits.ui.api.__file__ ),
                      'demo', 'Applications' ) ]
    
#--[FileInfo Class]-------------------------------------------------------------

class FileInfo ( HasPrivateTraits ):
    
    file_name = File
    name      = Property
    size      = Property
    time      = Property
    date      = Property
    
    @cached_property
    def _get_name ( self ):
        return basename( self.file_name )
        
    @cached_property
    def _get_size ( self ):
        return getsize( self.file_name )
        
    @cached_property
    def _get_time ( self ):
        return strftime( '%I:%M:%S %p', 
                         localtime( getmtime( self.file_name ) ) )
        
    @cached_property
    def _get_date ( self ):
        return strftime( '%m/%d/%Y', 
                         localtime( getmtime( self.file_name ) ) )
                         
#--[FileInfoAdapter Class]------------------------------------------------------

class FileInfoAdapter ( TabularAdapter ):
    
    columns = [ ( 'File Name', 'name' ), 
                ( 'Size',      'size' ), 
                ( '',          'big'  ),
                ( 'Time',      'time' ),
                ( 'Date',      'date' ) ]
                
    even_bg_color  = wx.Colour( 201, 223, 241 )
    font           = 'Courier 10'
    size_alignment = Str( 'right' )
    time_alignment = Str( 'right' )
    date_alignment = Str( 'right' )
    big_text       = Str
    big_width      = Float( 18 )
    big_image      = Property
    
    def _get_big_image ( self ):
        size = self.item.size
        if size > 65536:
            return 'red_ball'
            
        return ( None, 'blue_ball' )[ size > 16384 ]
   
#--[Tabular Editor Definition]--------------------------------------------------

tabular_editor = TabularEditor(
    editable   = False,
    selected   = 'file_info',
    adapter    = FileInfoAdapter(),
    operations = [],
    images     = [ ImageResource( 'blue_ball', search_path = search_path ),
                   ImageResource( 'red_ball',  search_path = search_path ) ]
)

#--[PythonBrowser Class]--------------------------------------------------------

class PythonBrowser ( HasPrivateTraits ):

    dir       = Directory
    files     = List( FileInfo )    
    file_info = Instance( FileInfo )
    code      = Code
    
    view = View(
        HSplit(
            Item( 'dir', style = 'custom' ),
            VSplit( 
                Item( 'files', editor = tabular_editor ),
                Item( 'code',  style = 'readonly' ),
                show_labels = False ),
            show_labels = False
        ),
        resizable = True,
        width     = 0.75,
        height    = 0.75
    )
    
    #-- Event Handlers ---------------------------------------------------------
    
    def _dir_changed ( self, dir ):
        self.files = [ FileInfo( file_name = join( dir, name ) )
                       for name in listdir( dir )
                       if ((splitext( name )[1] == '.py') and 
                           isfile( join( dir, name ) )) ]
                           
    def _file_info_changed ( self, file_info ):
        fh = None
        try:
            fh = open( file_info.file_name, 'rb' )
            self.code = fh.read()
        except:
            pass
            
        if fh is not None:
            fh.close()

#--[Example*]-------------------------------------------------------------------

demo = PythonBrowser( dir = dirname( enthought.traits.api.__file__ ) )

