#!/usr/bin/python
#vim:set ts=4 sts=4 sw=4 sta et ai:

import os, time
from wxPython.wx import *
import Image

class ImageWindow(wxScrolledWindow):
    def __init__(self, parent, id = -1, size = wxDefaultSize):
        wxScrolledWindow.__init__(self, parent, id, wxPoint(0, 0), size, wxSUNKEN_BORDER | wxCLIP_CHILDREN)
        EVT_PAINT(self, self.OnPaint)
                
        self.img = None
        self.pimg = None
        self.bmp = None
        
        
        self.angle = 0
        self.width = None
        self.height = None
        self.changed = 0

    def GetWidth(self):
        return self.GetSize().GetWidth()


    def GetHeight(self):
        return self.GetSize().GetHeight()

    def OnPaint(self, event):
        if self.bmp is None: return
        dc = wxPaintDC(self)
        self.PrepareDC(dc)
        self.DrawBitmap(dc)

    def DrawBitmap(self, dc = None):
        if dc is None:
            dc = wxClientDC(self)
            self.PrepareDC(dc)

        if(self.changed):
            tmppimg = self.pimg
            Width = self.width
            Height = self.height
            
            if(self.angle != 0):
                tmppimg = tmppimg.rotate(self.angle)
                if((self.angle == 90) or (self.angle == 270)):
                    Width = self.height
                    Height = self.width
            if((tmppimg.size[0] != Width) or (tmppimg.size[1] != Height)):
                tmppimg = tmppimg.resize((Width, Height))
                
                       
            tmpwimg = wxEmptyImage(Width, Height)
            tmpwimg.SetData(tmppimg.tostring())
            self.bmp = tmpwimg.ConvertToBitmap()
            self.ScrollBars()
            self.Changed(0)
            
        #---- Center the image in the window
        if(self.GetWidth() > self.bmp.GetWidth()):
            Xstart = (self.GetWidth() / 2) - (self.bmp.GetWidth() / 2)
        else:
            Xstart = 0
        if(self.GetHeight() > self.bmp.GetHeight()): 
            Ystart = (self.GetHeight() / 2) - ( self.bmp.GetHeight() / 2)
        else:
            Ystart = 0

        self.SetSize(self.GetSize())
        dc.SetBrush(wxBrush(wxSystemSettings_GetSystemColour(wxSYS_COLOUR_WINDOW)))
        dc.BeginDrawing()
        dc.Clear()
        dc.DrawBitmap(self.bmp, Xstart, Ystart)
        dc.EndDrawing()

    def Changed(self, changed):
        self.changed = changed
        
    def ScrollBars(self):
        PixPerScrollH = 15
        PixPerScrollW = 15

        UnitsH = self.bmp.GetHeight() / PixPerScrollH
        if(self.bmp.GetHeight() % PixPerScrollH): ++UnitsH
        UnitsW = self.bmp.GetWidth() / PixPerScrollW
        if(self.bmp.GetWidth() % PixPerScrollW): ++UnitsW
	self.SetScrollbars(PixPerScrollW, PixPerScrollH, UnitsW, UnitsH)

    def FitBoth(self):
        ratio = float(self.GetWidth()) / float(self.img.GetWidth())
        print "ratio",ratio
        Width = self.img.GetWidth() * ratio
        Height = self.img.GetHeight() * ratio
        ratio = float(self.GetHeight()) / float(Height)
        if(ratio < 1):
            Width = Width * ratio
            Height = Height * ratio
        self.width = Width
        self.height = Height
        self.Changed(1)
        self.DrawBitmap()
        self.Refresh()


    def FitWidth(self):
        if((self.angle == 90) or (self.angle == 270)):
            ratio = float(self.GetWidth() - 10) / float(self.pimg.size[1])
        else:
            ratio = float(self.GetWidth() - 10) / float(self.pimg.size[0])
        print "ratio",ratio
        self.width = self.img.GetWidth() * ratio
        self.height = self.img.GetHeight() * ratio
        self.Changed(1)
        self.DrawBitmap()
        self.Refresh()

    def FitHeight(self):
        ratio = float(self.GetHeight() - 10) / float(self.img.GetHeight())
        print "ratio",ratio
        self.width = self.img.GetWidth() * ratio
        self.height = self.img.GetHeight() * ratio
        self.Changed(1)
        self.DrawBitmap()
        self.Refresh()

    def Rotate90(self):
        self.angle = (self.angle + 90) % 360
        self.Changed(1)
        self.DrawBitmap()
        self.Refresh()
        
    def Restore(self):
        self.width = self.pimg.size[0]
        self.height = self.pimg.size[1]
        self.angle = 0
        self.Changed(1)

    def SetImage(self, img):
        self.img = img
        imgsize = (self.img.GetWidth(), self.img.GetHeight())
        self.pimg = Image.fromstring("RGB", imgsize, self.img.GetData())
        self.width = self.pimg.size[0]
        self.height = self.pimg.size[1]
        self.Changed(1)
        self.DrawBitmap()

        
class ImageViewer(wxFrame):
    def __init__(self, parent, id = -1, size = wxDefaultSize):
        wxFrame.__init__(self, NULL, id, "Image Viewer", wxDefaultPosition, wxSize(600,500))

        #---- Set up menu
        menu = wxMenu()
        imgmenu = wxMenu()
        ID_OPEN = NewId()
        ID_EXIT = NewId()
        ID_WIDTH = NewId()
        ID_HEIGHT = NewId()
        ID_BOTH = NewId()
        ID_ROTATE = NewId()
        
        imgmenu.Append(ID_WIDTH, "Fit to &width", "")
        imgmenu.Append(ID_HEIGHT, "Fit to &Height", "")
        imgmenu.Append(ID_BOTH, "Fit &Page", "")
        imgmenu.Append(ID_ROTATE, "Rotate 90 degrees", "")
        
        menu.Append(ID_OPEN, "&Open", "Open an image")
        menu.Append(ID_EXIT, "E&xit", "Exit")
        menuBar = wxMenuBar()
        menuBar.Append(menu, "&File")
        menuBar.Append(imgmenu, "&Image")
        self.SetMenuBar(menuBar)
        self.LastOpenDir = os.getcwd()

        EVT_MENU(self, ID_EXIT, self.OnExit)
        EVT_MENU(self, ID_OPEN, self.OnOpen)
        EVT_MENU(self, ID_BOTH, self.OnBoth)

        EVT_MENU(self, ID_HEIGHT, self.OnHeight)
        EVT_MENU(self, ID_WIDTH, self.OnWidth)
        EVT_MENU(self, ID_ROTATE, self.OnRotate)

        #---- Define split-pane
        splitter = wxSplitterWindow(self, -1, style=wxNO_3D|wxSP_3D)
        splitter.SetMinimumPaneSize(1)

        #---- Create left pane
        leftpanel = wxPanel(splitter, -1, style=wxSIMPLE_BORDER)
        
        #---- Create image viewer
        self.viewer = ImageWindow(splitter, -1)
        wxInitAllImageHandlers()

        #---- Split the windows
        splitter.SplitVertically(leftpanel, self.viewer)
        splitter.SetSashPosition(40, true)
        
    def OnExit(self, evt):
        self.Close(true)

    def OnOpen(self, evt):
        dlg = wxFileDialog(self, "Choose a file", self.LastOpenDir, "", "*.*", wxOPEN)
        if dlg.ShowModal() == wxID_OK:
            image = wxImage(os.path.join(dlg.GetDirectory(), dlg.GetFilename()))
            self.viewer.SetImage(image)
            self.LastOpenDir = dlg.GetDirectory()

        dlg.Destroy()

    def OnHeight(self, evt):
        self.viewer.FitHeight()

    def OnWidth(self, evt):
        self.viewer.FitWidth()

    def OnBoth(self, evt):
            self.viewer.FitBoth()

    def OnRotate(self, evt):
            self.viewer.Rotate90()

class ImageApp(wxApp):
    def OnInit(self):
        frame = ImageViewer(self)
        frame.Show(TRUE)
        return TRUE

app = ImageApp(0)
app.MainLoop()
