img_view.py :  » Business-Application » hylaPEx » hylapex » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Business Application » hylaPEx 
hylaPEx » hylapex » img_view.py
#!/usr/bin/python
# -*- coding: utf-8 -*-

import os, tempfile, sys, traceback

import wx
from library.ftp import read_conf
import wx_util

#Cursor direction
handle_LEFT = 1
handle_RIGHT = 2
handle_TOP = 4
handle_BOTTOM = 8

def create(parent, img2open):
    return Img_view(parent, img2open)

class Img_view(wx.Frame):
    def __init__(self, parent, img2open = [], close = 1, text4print = '',
            paths = '', opt_cls='', funct4save='', only4test=0, modify=0):
        super(Img_view, self).__init__(parent, -1, 'FaxView', style=wx.WANTS_CHARS|wx.DEFAULT_FRAME_STYLE)
        
        self._p = wx.Panel(self, style=wx.WANTS_CHARS)
        
        #self.SetBackgroundColour(wx.Colour(225, 225, 225))
        
        self.opt_cls = opt_cls
        self.paths = paths
        self.text4print = text4print
        self.funct4save = funct4save
        
        #Control paths
        if not paths:
            self.pref = read_conf.pref('hylapex')
            self.my_path = self.pref.get_my_path()
            self.paths = None
        else:
            self.my_path = paths.my_path
            self.paths = paths
                
        self.my_path_imgs = os.path.join(self.my_path, 'imgs')
        
        self.close = close
        
        self.modify = modify

        #Go with panel, buttons and sizer
        self._sizer()
        
        #I put here this code because I must resize the frame after set the sizer
        toolPos = wx.Size(0,0)
        if paths:
            #Image view position
            if not self.opt_cls.has_option('imgview_sp'):
                self.CenterOnParent()
            else:
                SizePos = self.opt_cls.get('imgview_sp')
                size, pos = SizePos.split(';')
                sizeX, sizeY = size.split(',')
                posX, posY = pos.split(',')
                
                self.SetSize(wx.Size(int(sizeX), int(sizeY)))
                self.SetPosition(wx.Point(int(posX), int(posY)))
            
            #Tool position
            if self.modify and self.opt_cls.has_option('imgview_tool_p'):
                pos = self.opt_cls.get('imgview_tool_p')
                posX, posY = pos.split(',')
                toolPos = wx.Point(int(posX), int(posY))                
                
        #Control type
        if type(img2open) != type( list() ):
            img2open = [img2open]
        self.img2open = img2open
        
        if not only4test:
            self.zoom = opt_cls.getint('cho_zoom')
            if not self.zoom:
                self.zoom = 40
            self.font4print = opt_cls.get('txt_fontsize')
        else:
            self.zoom = 100
            self.font4print = 10
            self.modify = 1
            self.SetSize(wx.Size(500,500))
            class _ren:
                def get(self, *args): return ""
                def set(self, *args): return ""
                def __class__(self, *args): return self.get()
            
            def funct4save(files):
                print "I'll try to load the just created image", files[0]
                os.system("kview %s" % files[0])
            
            self.opt_cls = _ren()
            self.ren = _ren()
            
            self.funct4save = funct4save
        
        #i18n
        if paths:
            self.ren = wx_util.rename_ctrls(self, 'img_view', paths.my_path, \
                lang = paths.language)
            self.ren.rename()
        elif not self.ren:
            self.ren = None
        
        #Modify vars
        self._lines4page = dict()
        self._text4page = dict()
        self._img4page = dict()
        
        self._list4undo = list()
        self._moving_text = -1
        self._moving_img  = -1
        self._dragging_text = 0
        self._drawing = 0
        self._dragging_img = 0
        # Update variables need for draw
        for i in xrange(len(self.img2open)+1):
            self._lines4page[i] = list()
            self._text4page[i] = list()
            self._img4page[i] = list()
            
        self.images = None
        
        #Control the images
        for i in self.img2open:
            if os.path.exists( str(i) ): continue
            self.img2open = list()
            wx.MessageBox('Image %s not found. Please close and reopen the program' % str(i) , 
                'Error', wx.ICON_ERROR)
            return

        #Current work image list
        self.images = internalImage(self.img2open)

        h, w = self.images.GetHeight(), \
               self.images.GetWidth()
        
        self.drawPanelInitSize = wx.Size(w, h)
        
        #Move the image
        self.grip = False
        self.grip_pos = wx.Point(0,0)
        
        #Polulate the wxchoice page 
        num_pages = len(img2open)
        for i in xrange(1, len(img2open) + 1):
            self.choPage.Append("%s / %s" % (i, num_pages))
        
        #and zoom
        self.zoomList = list()
        for i in xrange(20, 150, 10):
            self.zoomList.append(i)
            self.choZoom.Append('%s' % i)
        #and rotation
        self.images.setRotationList( (0, 90, 180, 270) )
        for i in self.images.getRotationList():
            self.choRot.Append(str(i))
        self.choPage.SetSelection(0)
        self.choRot.SetStringSelection('0')
        self.choZoom.SetStringSelection('%s' % self.zoom)
        
        #Enable / disable widgets
        self.btprev.Enable(False)
        if len(img2open) == 1:
            for widg in (self.btnext, self.btprev, \
                self.choPage):
                widg.Enable(False)
        
        self._ResizePanel()
        
        if self.modify:
            import tools_view
            self.tools = tools_view.Tools(self, paths, pos=toolPos)
            self.CtrlCursor()
            self.tools.Show()
        
        self._dcDrawLines = None
            
    def doPaint(self, event):
        """ Respond to the paint method
        """
        if self.images:
            self.images.loadImage()
        else:
            event.Skip()
            return
        
        self.SetTitle( 'FaxView -- %s' % self.images.getImageName() )
        
        dc = wx.PaintDC(self.drawPanel)
        self.drawPanel.PrepareDC(dc)
        dc.SetUserScale(self._getCurrentZoom(), self._getCurrentZoom())
        self._privateDraw(dc)
        
    def doPrint(self, event):
        """ Go with printer
        """
        printData = wx.PrintData()
        printData.SetPaperId(wx.PAPER_A4)
        
        #Black and white
        printData.SetColour(0)
        pdlgdata = wx.PrintDialogData(printData)
        printer = wx.Printer(pdlgdata)
        printout = myPrintOut(self.images, text = self.text4print, 
                    font4print = self.font4print)
        printer.Print(self, printout)
    
    def doClose(self, event=None):
        """ Perform close operation
        """
        modified = 0
        
        for val in self._lines4page:
            if self._lines4page[val]:
                modified = 1
                break
        for val in self._text4page:
            if modified: break
            if self._text4page[val]:
                modified = 1
        
        for val in self._img4page:
            if self._img4page[val]:
                modified = 1
                break
        
        if modified:
            if self.ren:
                title = self.ren.get('_save')
                quest = self.ren.get('_save_modify')
            else:
                title = self.ren.get('Save?')
                quest = self.ren.get('I found some modify. Do you want to save?')
            
            dlg = wx.MessageDialog(self, quest, title, wx.ICON_QUESTION | wx.YES_NO)
            if dlg.ShowModal() == wx.ID_NO:
                modified = 0
            dlg.Destroy()
        
        if self.funct4save and modified:
            self.funct4save( self.savePanelToBmp() )
        
        #Save img_view size and position
        sx, sy = self.GetSize()
        px, py = self.GetPosition()
        size = "%s,%s" % (sx, sy)
        pos = "%s,%s" % (px, py) 
        if not self.IsIconized():
            self.opt_cls.set('imgview_sp', "%s;%s"  % (size, pos) )
        
        #Save tool_view position
        if self.modify:
            pTx, pTy = self.tools.GetPosition()
            self.opt_cls.set('imgview_tool_p', "%s,%s" % (pTx, pTy) )
        
        self.Destroy()
        print 'close imgview'
        
    def doNext(self, event):
        """ Display Next page
        """
        if len(self.img2open)-1 == self.images.getCurrentPage(): return
        self.images.addToCurrentPage( 1 )
        self._btCtrl()
        self.choPage.SetSelection(self.images.getCurrentPage())
        
        self._setRotateChoice()
        
        self.drawPanel.Refresh()

    def doPreview(self, event):
        """ Display the preview page
        """
        
        if self.images.getCurrentPage() == 0: return
        self.images.addToCurrentPage( -1 )
        self._btCtrl()
        self.choPage.SetSelection(self.images.getCurrentPage())
        
        self._setRotateChoice()
        
        self.drawPanel.Refresh()

    def doRotDx(self, event):
        """
        """
        self._rotate(1)
        
    def doRotSx(self, event):
        """
        """
        self._rotate(0)

    def doZoomIn(self, event):
        """
        """
        self._adjustZoom('n')
    
    def doZoomOut(self, event):
        """
        """
        self._adjustZoom('p')
        
    def doZoomChoice(self, event):
        """ Respond to the zoom choice
        """
        self.zoom = int(event.GetString())
        self._ResizePanel()
        
    def doRotChoice(self, event):
        """ Do rotation choice
        """
        self._intRotChoice( int(event.GetString()) )
        
    def doPageChoice(self, event):
        """ Choose page
        """
        self.images.setCurrentPage( int(event.GetString().split("/")[0]) -1 )
        self._btCtrl()
        self.drawPanel.Refresh()
    
    def doMouseEvt(self, event):
        """ Do the mouse events
        """
        x, y = self.ConvertEventCoords(event)
        x, y = int(x), int(y)
        
        if self.modify:
            side = None
            data = self._getSideOverBorder(x, y)
            if data: side = data[1] 
            self.CtrlCursor(side)
            
        if not (event.LeftDown() or event.Dragging() or event.LeftUp()):
            event.Skip()
            
            # Ignore mouse movement without click/drag.
            return 

        #Pay attention to the pen moves
        if self.modify and self.tools.bt_pen.GetValue():
            self.CtrlLine(event)
        elif self.modify and self.tools.bt_text.GetValue():
            self.CtrlText(event)
        elif self.modify and self.tools.bt_img.GetValue():
            self.CtrlImage(event)
        else:
            self.CtrlMove(event)
    
    def doKeyEvt(self, evt):
        """ Respond to the the key (from F1 to F4)
        """
        
        kc = evt.GetKeyCode()
        lst_k = [wx.WXK_F1, wx.WXK_F2, wx.WXK_F3, wx.WXK_F4]
        
        if not kc in lst_k:
            evt.Skip()
            return
        
        d_img = {}
        
        for num in xrange(5):
            #load the 4 keys from the conf
            prev_name = "preview_img_sc_f%s" % num
            
            if self.opt_cls.has_option(prev_name):
                d_img[num] = self.opt_cls.get(prev_name)
            else:
                d_img[num] = None
        
        img_path = d_img[lst_k.index(kc) + 1]
        
        if not img_path:
            #no image found. Return
            evt.Skip()
            return
        
        self.tools.SetButton(self.tools.bt_img, 1)
        
        self._add_image(10, 10, img_path)
        
        
    def doMouseWheel(self, event):
        """ Scroll the frame, not move the wxChoice
        """
        if event.GetWheelRotation() < 0:
            self.drawPanel.ScrollLines(2)
        else:
            self.drawPanel.ScrollLines(-2)
    
    def _ResizePanel(self, su=20):
        """ Work with zoom, size is used only first time
        """
        w, h = self.images.GetWidth(), self.images.GetHeight()
        w = w * self._getCurrentZoom()
        h = h * self._getCurrentZoom()
        self.drawPanel.SetScrollbars(su, su, w/su, h/su)
        self.panelSizer.Layout()
        self.drawPanel.Refresh()
        
    def _adjustZoom(self, side, adjCho=1):
        pos = self.zoomList.index(self.zoom)
        if side == 'p':
            #I cannot do preview zoom on the first zoom
            if not pos == 0: 
                self.zoom = self.zoomList[pos -1]
        else:
            #I cannot do preview zoom on the first zoom
            if pos != len(self.zoomList)-1: 
                self.zoom = self.zoomList[pos +1]
        if adjCho:
            self.choZoom.SetStringSelection('%i' % self.zoom)
        
        self._ResizePanel()
    
    def _rotate(self, side):
        """ Rotate the image
        """ 
        if side:
            self.images.rotateDx()
        else:
            self.images.rotateSx()
        
        #Update the choice
        self._setRotateChoice()
        
        self._ResizePanel()
        self.drawPanel.Refresh()

    def _btCtrl(self):
        """ Control the button enable/disable state
        """
        cp = self.images.getCurrentPage()
        if cp == 0:
            self.btnext.Enable(True)
            self.btprev.Enable(False)
        elif cp == len(self.img2open) -1:
            self.btnext.Enable(False)
            self.btprev.Enable(True)
        else:
            self.btnext.Enable(True)
            self.btprev.Enable(True)
            
    
    def _SaveImages(self, path):
        """ Help method for save the images
        """
        dlg = wx.MessageDialog(self, self.parent.ren.get('_save_modify'),
            self.parent.ren.get('_save'), wx.ICON_QUESTION | wx.YES_NO)
        ret = dlg.ShowModal() == wx.ID_YES
        dlg.Destroy()
        if ret:
            files = list()
            for num, page in enumerate(self.img2open):
                self.choose_page(num+1, 1)
                fo = tempfile.mkstemp(dir=path, suffix = '%s.tiff' % str(num))[1]
                page.SetOption(wx.IMAGE_OPTION_COMPRESSION, "2")
                page.SaveFile(fo, wx.BITMAP_TYPE_TIF)
                files.append(fo)
            return files
        else:
            return ''
    
    def CtrlCursor(self, side=None):
        """ Control and set the current cursor
        """
        if self._dragging_img:
            return
            
        if side:
            
            if (side & handle_RIGHT) and (side & handle_BOTTOM): cur = wx.CURSOR_SIZENWSE
            elif (side & handle_RIGHT) and (side & handle_TOP): cur = wx.CURSOR_SIZENESW
            elif (side & handle_LEFT) and (side & handle_BOTTOM): cur = wx.CURSOR_SIZENESW
            elif (side & handle_LEFT) and (side & handle_TOP): cur = wx.CURSOR_SIZENWSE
            
            elif side & handle_RIGHT: cur = wx.CURSOR_SIZEWE
            elif side & handle_LEFT: cur = wx.CURSOR_SIZEWE
            elif side & handle_BOTTOM: cur = wx.CURSOR_SIZENS
            elif side & handle_TOP: cur = wx.CURSOR_SIZENS
            else:
                return
        
        else:
            if self.tools.bt_pen.GetValue(): cur = wx.CURSOR_PENCIL
            elif self.tools.bt_text.GetValue(): cur = wx.CURSOR_CROSS
            elif self.tools.bt_img.GetValue(): cur = wx.CURSOR_DEFAULT
            else: cur = wx.CURSOR_HAND
        
        self.drawPanel.SetCursor(wx.StockCursor(cur))
        
    def CtrlMove(self, event):
        """ Move the image over mouse
        """
        MN = 20
        if event.LeftDown():
            self.grip = True
            mx, my = event.GetPosition()
            mx, my = mx/MN, my/MN
            self.grip_pos = mx, my
            self.SetCursor(wx.StockCursor(wx.CURSOR_SIZING))
        elif event.Dragging():
            x, y = self.ScreenToClient(wx.GetMousePosition())
            vx, vy = self.drawPanel.GetViewStart()
            if self.grip:
                ox, oy = self.grip_pos
                mx, my = event.GetPosition()
                mx, my = mx/MN, my/MN
                sx, sy = vx+(ox-mx), vy+(oy-my)
                self.drawPanel.Scroll(sx, sy)
                self.grip_pos = mx, my
        elif event.LeftUp() and self.grip:
            self.SetCursor(wx.NullCursor)
            self.grip = False
        else:
            event.Skip()
        
    def CtrlLine(self, event):
        if event.LeftDown():
            self.SetXY(event)
            self.curLine = []
            self._drawing = True
            
        elif event.Dragging() and self._drawing:
            try:
                line_w = self.tools.txt_line_w.GetValue()
                lw = int(line_w)
            except ValueError:
                event.Skip()
                dlg = wx.MessageDialog(self,  '%s %s %s' % 
                    (self.ren.get('value', 1), line_w,  self.ren.get('invalid', 1)),
                        self.ren.get('error', 1), wx.ICON_ERROR)
                dlg.ShowModal()
                dlg.Destroy()
                return
            x, y = self.ConvertEventCoords(event)
            coords = (self.x, self.y) + (x, y)
            self._drawLineTime(coords,lw = lw, col=self.tools.CurColor)
            data = (coords, lw, self.tools.CurColor)
            self.curLine.append(data)
            self.SetXY(event)
            
        elif event.LeftUp() and self._drawing:
            self._lines4page[self.images.getCurrentPage()].append(self.curLine)
            self.curLine = []
            self._drawing = False
            #self.drawPanel.Refresh()
            self._list4undo.append('l')
            self._drawLineTime(end=1)
            
    def CtrlText(self, event):
        x, y = self.ConvertEventCoords(event)
        
        text_data = self._getTextAt(x,y)
        
        if text_data and self._moving_text == -1:
             tmp_data, self._moving_text = text_data
             text, xT, yT, font = tmp_data
        
        if event.LeftDown() and self._moving_text == -1:
            """ New text
            """
            dlg = wx.TextEntryDialog(self, self.ren.get('_insert_text'),
                self.ren.get('text', 1), '')
            text = ''
            if dlg.ShowModal() == wx.ID_OK:
                text = dlg.GetValue()
            dlg.Destroy()
            if not text: return
            
            data = (text, x, y, self.tools._GetFont(), self.tools.CurColor)
            self._text4page[self.images.getCurrentPage()].append(data)
            self._list4undo.append('t')
            self.drawPanel.Refresh()
        
        elif event.LeftDown() and self._moving_text != -1:
            #Calculate the relative position
            xT, yT = self._text4page[self.images.getCurrentPage()][self._moving_text][1:3]
            self._textDx = int(x - xT)
            self._textDy = int(y - yT)
            self._oldObjPos = wx.Point(x,y)
            self._drawObjRect(x, y)
            
        elif event.LeftUp() and self._moving_text != -1 and not self._dragging_text:
            """ Modify text
            """
            text, xT, yT = self._text4page[self.images.getCurrentPage()][self._moving_text][:3]
            dlg = wx.TextEntryDialog(self, self.ren.get('_insert_text'),
                self.ren.get('text', 1), text)
            
            if dlg.ShowModal() == wx.ID_OK:
                text = dlg.GetValue()
                dlg.Destroy()
            else:
                dlg.Destroy()
                return
            self._text4page[self.images.getCurrentPage()].pop(self._moving_text)
            dlg.Destroy()
            if not text: return

            data = (text, xT, yT , self.tools._GetFont(), self.tools.CurColor)
            self._text4page[self.images.getCurrentPage()].append(data)
            self._moving_text = -1
            self.drawPanel.Refresh()
            
        elif event.LeftUp() and self._moving_text != -1 and self._dragging_text:
            """We have finished to drag
            """
            text, xT, yT, font = \
                self._text4page[self.images.getCurrentPage()].pop(self._moving_text)[:4]
            data = (text, x - self._textDx, y -self._textDy , self.tools._GetFont(), self.tools.CurColor)
            self._text4page[self.images.getCurrentPage()].append(data)
            self._dragging_text = 0
            self._moving_text = -1
            self.drawPanel.Refresh()
            
        elif event.Dragging() and self._moving_text != -1:
            self._dragging_text = 1
            oldX, oldY = self._oldObjPos
            if (x != oldX) or ( y != oldY ):
                self._drawObjRect(oldX, oldY)
                self._oldObjPos = wx.Point(x,y)
                self._drawObjRect(x, y)
    
    def CtrlImage(self, event):
        """
        """
        
        x,y = map(int, self.ConvertEventCoords(event))
        data = self._getImageAt(x,y, not event.Dragging())
        
        if self._moving_img == -1:
            #add a new image
            self._add_image(x, y)
            
        elif event.LeftDown():
            """Start to move. Calculate the relative position
            """
            data = self._getSideOverBorder(x,y)
            
            if data:
                self._resizing = data
            else:
                self._resizing = None
            
            if not self._img4page:
                return
            
            xT, yT = self._img4page[self.images.getCurrentPage()][self._moving_img][1:3]
            self._textDx = int(x - xT)
            self._textDy = int(y - yT)
            self._oldObjPos = wx.Point(x,y)
            self._drawObjRect(x, y)
            
        elif event.LeftUp():
            """We have finished to drag or on click over an image
            """
            if self._dragging_img:
                bmp, xTPos, yTPos, xTsize, yTsize = \
                    self._img4page[self.images.getCurrentPage()].pop(self._moving_img)
                
                oldX, oldY = self._oldObjPos
                if self._resizing:
                    newW, newH = xTsize, yTsize
                    
                    side_res = self._resizing[1]
                    
                    if side_res & handle_BOTTOM:
                        newH = yTsize + (y - oldY)
                    if side_res & handle_TOP:
                        newH = yTsize + (oldY - y)
                        yTPos = y
                    
                    if side_res & handle_RIGHT:
                        newW = xTsize + (x - oldX)
                    if side_res & handle_LEFT:
                        newW = xTsize + (oldX - x)
                        xTPos = x
                    
                    img = wx.ImageFromBitmap(bmp)
                    img.Rescale(newW, newH)
                    
                    data = (wx.BitmapFromImage(img), xTPos, yTPos, newW, newH)
                else:
                    data = (bmp, x -self._textDx, y -self._textDy, xTsize, yTsize)
                
                self._img4page[self.images.getCurrentPage()].append(data)

            self._dragging_img = 0
            self._moving_img = -1
            self.drawPanel.Refresh()
            #wx.FutureCall(20, self._drawObjRect, x, y)
        
        
        elif event.Dragging():
            
            self._dragging_img = 1
            
            if self._resizing:
                return
            
            oldX, oldY = self._oldObjPos
            if (x != oldX) or ( y != oldY ):
                self._drawObjRect(oldX, oldY)
                self._oldObjPos = wx.Point(x,y)
                self._drawObjRect(x, y)

    def GoUndo(self):
        """ Process the undo command
        """
        if not self._list4undo: return
        
        type = self._list4undo.pop()
        if type == 'l':
            self._lines4page[self.images.getCurrentPage()].pop()
        elif type == 't':
            self._text4page[self.images.getCurrentPage()].pop()
        elif type == 'i':
            self._img4page[self.images.getCurrentPage()].pop()

            
        self.drawPanel.Refresh()
            
    def savePanelToBmp(self):
        """ Save the current panel to a bitmap
        """
        files = list()
        for n in xrange( self.images.getNumberPage() ):
            self.images.setCurrentPage(n)
            if not (self._lines4page[n] or self._text4page[n] or self._img4page[n]) :
                files.append(self.images.getImageName())
                continue
            
            width, height = self.images.GetWidth(), self.images.GetHeight()
            destDC = wx.MemoryDC()
            bmp = wx.EmptyBitmap(width, height)
            destDC.SelectObject(bmp)
            self._privateDraw(destDC)
            destDC.SelectObject(wx.NullBitmap)
            fo = tempfile.mkstemp(suffix = '%s.png' % n)[1]
            bmp.SaveFile(fo, wx.BITMAP_TYPE_PNG)        
            files.append(fo)
        return files
    
    def SetXY(self, event):
        x, y = self.ConvertEventCoords(event)
        self.x, self.y = x, y
    
    def ConvertEventCoords(self, event):
        xView, yView = self.drawPanel.GetViewStart()
        xDelta, yDelta = self.drawPanel.GetScrollPixelsPerUnit()
        x, y = (event.GetX() + (xView * xDelta),
                    event.GetY() + (yView * yDelta))
        return x / self._getCurrentZoom(), y / self._getCurrentZoom()

        
    def _sizer(self):
        
        #Buttons list
        btList = ((self.doPrint, 'printer.jpg', (25,25)), (self.doClose, 'out.png',(25,25)),
            (self.doNext, 'next.jpg', (15,15)), (self.doPreview, 'prev.jpg', (15,15)) ,
            (self.doRotDx, 'rotdx.jpg',(15,15)), (self.doRotSx, 'rotsx.jpg',(15,15)),
            (self.doZoomIn, 'zoomin.jpg',(15,15)), ( self.doZoomOut, 'zoomout.jpg',(15,15)),
            )
        
        for inst_but in btList:
            bt_name = 'bt' + inst_but[1].split('.')[0]
            setattr(self, bt_name , btCtrl(self._p, self.my_path_imgs, inst_but))
        
        self.Bind(wx.EVT_CLOSE, self.doClose)
        #Panel
        self.drawPanel = wx.ScrolledWindow(self._p, -1, style=wx.SUNKEN_BORDER)
        self.drawPanel.EnableScrolling(True, True)
        
        self.drawPanel.SetBackgroundColour(wx.WHITE)
        
        self.drawPanel.Bind(wx.EVT_PAINT, self.doPaint)
        
        self.Bind(wx.EVT_MOUSEWHEEL, self.doMouseWheel)
        
        #if self.modify:
        self.drawPanel.Bind(wx.EVT_MOTION, self.doMouseEvt)
        self.drawPanel.Bind(wx.EVT_LEFT_DOWN, self.doMouseEvt)
        self.drawPanel.Bind(wx.EVT_LEFT_UP, self.doMouseEvt)
        
        for i in (wx.EVT_KEY_DOWN, ):
            self.Bind(i, self.doKeyEvt)
            self.drawPanel.Bind(i, self.doKeyEvt)
        
        wx.CallAfter(self.drawPanel.SetFocus)
        
        self.panelSizer = wx.BoxSizer(wx.VERTICAL)        
        #Buttons sizer
        self.btSizer = wx.FlexGridSizer(2,11,1,1)
        self.btSizer.SetFlexibleDirection(wx.HORIZONTAL)
        
        self.lbl_rotation = wx.StaticText(self._p, -1, 'Rotazione')
        self.lbl_pag = wx.StaticText(self._p, -1, 'Pagine')
        self.lbl_zoom = wx.StaticText(self._p, -1, 'Zoom')
        
        self.btSizer.Add(wx.Size(0,0),0)
        self.btSizer.Add(self.lbl_zoom, 0, wx.ALIGN_CENTER)
        self.btSizer.Add(wx.Size(0,0),0)
        self.btSizer.Add(wx.Size(0,0),0)
        self.btSizer.Add(self.lbl_rotation ,0, wx.ALIGN_CENTER)
        self.btSizer.Add(wx.Size(0,0),0)
        self.btSizer.Add(wx.Size(0,0),0)
        self.btSizer.Add(self.lbl_pag ,0, wx.ALIGN_CENTER)
        self.btSizer.Add(wx.Size(0,0),0)
        self.btSizer.Add(wx.Size(0,0),0)
        self.btSizer.Add(wx.Size(0,0),0)
        
        self.choZoom = wx.Choice(self._p, -1)
        self.choZoom.Bind(wx.EVT_CHOICE, self.doZoomChoice)
        self.choZoom.Bind(wx.EVT_MOUSEWHEEL, self.doMouseWheel)
        
        self.choRot = wx.Choice(self._p, -1)
        self.choRot.Bind(wx.EVT_CHOICE, self.doRotChoice)
        self.choRot.Bind(wx.EVT_MOUSEWHEEL, self.doMouseWheel)
        
        self.choPage = wx.Choice(self._p, -1)
        self.choPage.Bind(wx.EVT_CHOICE, self.doPageChoice)
        self.choPage.Bind(wx.EVT_MOUSEWHEEL, self.doMouseWheel)
        
        #self.chkA4 = wx.CheckBox(self, -1)
        
        ACV = wx.ALIGN_CENTER_VERTICAL
        RLA = wx.RIGHT | wx.LEFT | ACV
        
        #End of line, init the second
        self.btSizer.Add(self.btzoomout, 0, RLA, 5)
        self.btSizer.Add(self.choZoom, 0, ACV )
        
        self.btSizer.Add(self.btzoomin, 0, RLA, 5)
        self.btSizer.Add(self.btrotsx, 0,RLA, 5)
        
        self.btSizer.Add(self.choRot, 0, ACV)
        
        self.btSizer.Add(self.btrotdx, 0,RLA, 5)
        self.btSizer.Add(self.btprev, 0,RLA, 5)
        
        self.btSizer.Add(self.choPage, 0, ACV)
        
        self.btSizer.Add(self.btnext, 0,RLA, 5)
        
        #self.btSizer.Add(self.chkA4, 0, RLA,3 )
        
        self.btSizer.Add(self.btprinter, 0,RLA, 5)
        self.btSizer.Add(self.btout, 0,RLA, 5)
        
        #Set min size
        self.btSizer.SetItemMinSize(self.choRot, wx.Size(70,20))
        self.btSizer.SetItemMinSize(self.choZoom, wx.Size(70,20))
        self.btSizer.SetItemMinSize(self.choPage, wx.Size(70,20))
        #Go with sizer
        
        self.panelSizer.Add(self.btSizer)
        self.panelSizer.Add(wx.Size(0,0),0)
        self.panelSizer.Add(self.drawPanel, 1, wx.EXPAND | wx.ALL, 10)
        self.panelSizer.SetItemMinSize(self.drawPanel, 200, 200)
        self._p.SetSizerAndFit(self.panelSizer)

    def _getCurrentZoom(self):
        """ Return the current zoom
            calculated into float value
        """
        return float(self.zoom) / 100.0
    
    def _intRotChoice(self, rot):
        """ Do the internal rotation choice
        """
        self.images.rotateByAngle(rot)
        self.drawPanel.Refresh()

    def _setRotateChoice(self):
        """ Set the right rotation into rotation choice 
            called from next, previews and _rotate
        """
        self.choRot.SetStringSelection('%s' % self.images.getCurrentAngleRotation())
        
    def _privateDraw(self, dc):
        """ Do the private draw
        """
        
        dc.BeginDrawing()
        bmp = self.images.getCurrentBmp()
        dc.DrawBitmap(bmp, 0,0)
        
        for data_bmp in self._img4page[self.images.getCurrentPage()]:
            bmp, x,y, w, h = data_bmp
            dc.DrawBitmap(bmp, x, y)
        
        for data_line in self._lines4page[self.images.getCurrentPage()]:
            for data in data_line:
                if len(data) != 3: continue
                coords, lw, color = data
                dc.SetPen(wx.Pen(color, lw))
                x1,y1,x2,y2 = coords
                dc.DrawLine(x1,y1,x2,y2)
        
        for data_text in self._text4page[self.images.getCurrentPage()]:
            text, x, y, font, color = data_text 
            dc.SetFont(font)
            dc.SetTextForeground(color)
            dc.DrawText(text, x, y)
        dc.EndDrawing()          

    def _drawLineTime(self, coords=None, end=None, lw = None, col=None):
        """ Draw the lines when the user draw on panel
        """
        if end:
            if self._dcDrawLines:
                self._dcDrawLines.EndDrawing()
                self._dcDrawLines = None
            return
        
        if not self._dcDrawLines:
            self._dcDrawLines = wx.ClientDC(self.drawPanel)
            self.drawPanel.PrepareDC(self._dcDrawLines)
            self._dcDrawLines.SetUserScale(self._getCurrentZoom(), self._getCurrentZoom())
            self._dcDrawLines.BeginDrawing()
        if lw: self._dcDrawLines.SetPen(wx.Pen(col, lw))
        self._dcDrawLines.DrawLine(*coords)
    
    def _drawObjRect(self, x,y):
        """
        """
        dc = wx.ClientDC(self.drawPanel)
        self.drawPanel.PrepareDC(dc)
        dc.SetUserScale(self._getCurrentZoom(), self._getCurrentZoom())
        dc.BeginDrawing()
        
        dc.SetPen(wx.BLACK_DASHED_PEN)
        dc.SetBrush(wx.TRANSPARENT_BRUSH)
        dc.SetLogicalFunction(wx.INVERT)
        
        bH, lH = x - self._textDx, y -self._textDy 
        W, H = self._obj_size
        dc.DrawRectangle(bH, lH, W, H)
        dc.EndDrawing()
        
    def _getImageAt(self, x, y, setMoving=1, ctrl_all=False):
        """
        """
        if self._moving_img != -1 and not ctrl_all:
            return self._img4page[self.images.getCurrentPage()]
        
        for num, img_data in enumerate( self._img4page[self.images.getCurrentPage()] ):
            bmp, xTPos, yTPos, xTsize, yTsize = img_data
            
            if ( ( x > xTPos and x < ( xTPos + xTsize ) ) and
                 ( y > yTPos and y < ( yTPos + yTsize) ) ):
                
                self._obj_size = wx.Point(xTsize, yTsize)
                if setMoving: self._moving_img = num
                
                return img_data, num
        
        return None
    
    def _getTextAt(self, x, y):
        """
        """
        dc = wx.MemoryDC()
        bmp = wx.EmptyBitmap(10,10)
        dc.SelectObject(bmp)
        dc.BeginDrawing()
        dc.SetUserScale(self._getCurrentZoom(), self._getCurrentZoom())
        dc.SetBackground(wx.WHITE_BRUSH)
        for num, t in enumerate( self._text4page[self.images.getCurrentPage()] ):
            text, xT, yT, font = t[:4]
            dc.Clear()
            dc.SetPen(wx.Pen(wx.BLACK, font.GetPointSize(), wx.SOLID))
            dc.SetBrush(wx.BLACK_BRUSH)
            dc.SetFont(font)
            size = dc.GetTextExtent(text)
            #dc.EndDrawing()
            xTsize = size[0]    #* self._getCurrentZoom()
            yTsize = size[1]    #* self._getCurrentZoom()
            xTPos = xT          #* self._getCurrentZoom()
            yTPos = yT          #* self._getCurrentZoom()
            if ( x > xTPos  and x <  ( xTPos + xTsize ) ) and \
                    (y > yTPos and y < (yTPos + yTsize) ):
                self._obj_size = wx.Point(xTsize, yTsize)
                return (text, xT, yT, font), num
        return None
    
    def _getSideOverBorder(self, x,y):
        """
        """
        
        img_data = self._getImageAt(x,y, False, True)
        
        if not img_data: 
            return None
        
        xTPos, yTPos, xTsize, yTsize = img_data[0][1:]
        
        N = 10
        ll, lr = xTPos - N, xTPos + N
        rl, rr = xTPos + xTsize - N, xTPos + xTsize + N
        
        tt, tb = yTPos - N, yTPos + N
        bt, bb = yTPos + yTsize - N, yTPos + yTsize + N
        
        img = img_data[0]
        
        if y > bt and y < bb and x > rl and x < rr:
            #right bottom
            return img, handle_BOTTOM | handle_RIGHT
        
        elif y > tt and y < tb and x > rl and x < rr:
            #right top
            return img, handle_TOP | handle_RIGHT
        
        elif y > bt and y < bb and x > ll and x < lr:
            #left bottom
            return img, handle_BOTTOM | handle_LEFT
        
        elif y > tt and y < tb and x > ll and x < lr:
            #right top
            return img, handle_TOP | handle_LEFT

        elif y > tt and y < tb and x > ll and x < (xTPos + xTsize + N):
            #top
            return img, handle_TOP
        
        elif y > bt and y < bb and x > ll and x < (xTPos + xTsize + N):
            #bottom
            return img, handle_BOTTOM
        
        elif x > rl and x < rr and y > tt and y < (yTPos + yTsize + N):
            #right
            return img, handle_RIGHT
        
        elif x > ll and x < lr and y > tt and y < (yTPos + yTsize + N):
            #left
            return img, handle_LEFT
            
        else:
            return None
    
    def _add_image(self, x, y, path=None):
        """ Add a new image to the canvas.
            If path is passed, not load the file dialog
        """
        #new image
        
        if path is None:
            path_file = self.opt_cls.get("path_save_preview_img")
            path_file = os.path.abspath(path_file)

            dlg = wx.FileDialog(self, self.ren.get("select_img"), path_file, 
                        wildcard="*.*")
            if dlg.ShowModal() != wx.ID_OK:
                dlg.Destroy()
                return
            path = dlg.GetPath()
            dlg.Destroy()
        
        if not os.path.exists(path):
            wx.MessageBox('Image %s not found.' % str(path),
                'Error', wx.ICON_ERROR)
            return
        
        self.opt_cls.set("path_save_preview_img", os.path.dirname(path))
        
        bmp = wx.Bitmap(path)
        if not bmp.Ok(): return
        w, h = bmp.GetSize()
        
        data = (bmp, x,y, int(w), int(h))
        self._img4page[self.images.getCurrentPage()].append(data)
        
        self._list4undo.append('i')
        
        wx.CallAfter(self.drawPanel.Refresh)

class internalImage(object):
    def __init__(self, imgList):
        """Init the class. Pass me the image list
        """

        self.imgList = imgList
        self.images = list()
        self.rotationPage = dict()
        for num, x in enumerate(self.imgList):
            self.images.append( None )
            self.rotationPage[num] = 0
        self.currentPage = 0
        self.loadImage()

    def getNumberPage(self):
        """ Return the number of pages
        """
        return len(self.imgList)
    
    def GetHeight(self):
        """
        """
        return self.images[self.currentPage].GetHeight()
        
    def GetWidth(self):
        """
        """
        return self.images[self.currentPage].GetWidth()
    
    def setCurrentPage(self, page):
        """
        """
        self.currentPage = page
        self.loadImage()
        
    def addToCurrentPage(self, value):
        """ Add the value to the current page
        """
        self.currentPage += value
    
    def getCurrentPage(self):
        """
        """
        return self.currentPage
    
    def getCurrentBmp(self):
        """ Return the current image, transformed into bitmap
        """
        return wx.BitmapFromImage( self.getCurrentImage())
    
    def getCurrentImage(self):
        """ Return the current image
        """
        try:
            return self.images[self.currentPage]
        except:
            return wx.EmptyImage(100,100)
    
    def setRotationList(self, list):
        """
        """
        self.rotationList = list

    def getRotationList(self):
        """
        """
        return self.rotationList
    
    def getCurrentAngleRotation(self):
        """
        """
        return self.getRotationList()[ self.getRotation() ]
                
    def setRotation(self, angle):
        """
        """
        self.rotationPage[self.currentPage] = angle

    def getRotation(self):
        """
        """
        return self.rotationPage[self.currentPage]
    
    def getPositionAngle(self, angle):
        """ Return the position of the angle into the rotation list
            Function like list().index(angle), but we don't know
            if the caller pass a tuple
        """
        for num, i in enumerate(self.getRotationList()):
            if i == angle:
                return num
        raise AttributeError
    
    def addToCurrentRotation(self, value):
        """
        """
        self.rotationPage[self.currentPage] += value

    def loadImage(self, rotation=0):
        """ Method for load only the current page image
        """
        
        #Don't reload the image
        if self.getCurrentImage() != None: return
        try:
            #else load the current page image
            self.images = [None for x in range(len(self.imgList) -1) ]
            image = wx.Image(self.imgList[self.currentPage])
            w, h = image.GetWidth(), image.GetHeight()
            if w > h:
                image.Rescale(w, w *1.4142)
            self.images.insert(self.currentPage, image)
            self.__rotateByPos(self.getRotation(), 1)
        except:
            print traceback.format_exc()
            pass
        
    def rotateDx(self):
        """
        """
        if self.getRotation() >= 3:
            self.setRotation( 0 )
        else:
            self.addToCurrentRotation( 1 )
        self.__rotate(1)
        
    def rotateSx(self):
        """
        """
        if self.getRotation() <= 0:
            self.setRotation( 3 )
        else:
            self.addToCurrentRotation( -1 )
        self.__rotate(0)
    
    def rotateByAngle(self, rotation):
        """
        """
        if not rotation in self.getRotationList():
            raise ValueError
        pos = self.getPositionAngle(rotation)
        self.loadImage()
        self.__rotateByPos(pos)
    
    def getImageName(self):
        """ Return the current image path/name
        """
        return self.imgList[ self.getCurrentPage() ]
    
    def __rotateByPos(self, pos, loadPage=0):
        """ Internal method for rotation
            Load page is need when I have to set 
            the initial rotation to a page
        """
        if loadPage: self.setRotation(0)
        #If are reselected the current zoom, return
        currRot = self.getRotation()
        if pos == 0 and currRot != 0:
            pos = - currRot
        if pos == 0: return
        elif pos in (1, -3):
            self.rotateDx()
        elif pos == 2: 
            self.rotateDx()
            self.rotateDx()
        elif pos in (3, -1):
            self.rotateSx()
        elif pos == -2:
            self.rotateSx()        
            self.rotateSx()
            
    def __rotate(self, side):
        """ Internal method for rotate the image
        """ 
        self.images[self.getCurrentPage()] = \
            self.images[self.getCurrentPage()].Rotate90(side)
        

class btCtrl(wx.BitmapButton):
    def __init__(self, parent, dirImages, values):
        doFunct, fileName, size = values
        fileName = os.path.join(dirImages, fileName)
        wx.BitmapButton.__init__(self, parent, bitmap=wx.NullBitmap, 
                                 style=wx.BU_AUTODRAW)
        self.Bind(wx.EVT_BUTTON, doFunct)
        self.SetBitmapLabel(wx_util.del_mask2img(fileName, size))
        
class myPrintOut(wx.Printout):
    """ Class to perform the printout """
    def __init__(self, images, title="Hylapex", text = '', font4print = 0):
        wx.Printout.__init__(self, title)
        self._images = images
        self.pages = images.getNumberPage()
        self.currentWorkerPage = images.getCurrentPage()
        self.currentPage = 0
        self.text = text
        self.font4print = font4print

    def GetPageInfo(self):
        return (1, self.pages, 1, self.pages)

    def OnPrintPage(self, page):
        dc = self.GetDC()
        print 'resolution: %s' % dc.GetPPI()
        self._images.setCurrentPage(page-1)
        bmap = self._images.getCurrentBmp()
        maxX, maxY = bmap.GetWidth(), bmap.GetHeight()
        # Let's have at least 50 device units margin
        marginX = 10
        marginY = 10
        # Add the margin to the graphic size
        maxX = maxX + (2 * marginX)
        maxY = maxY + (2 * marginY)
        # Get the size of the DC in pixels
        (w, h) = dc.GetSizeTuple()
        # Calculate a suitable scaling factor
        scaleX = float(w) / maxX
        scaleY = float(h) / maxY
        # Use x or y scaling factor, whichever fits on the DC
        actualScale = min(scaleX, scaleY)
        # Calculate the position on the DC for centering the graphic
        posX = (w - (maxX * actualScale)) / 2.0
        posY = (h - (maxY * actualScale)) / 2.0
        # Set the scale and origin
        dc.SetUserScale(actualScale, actualScale)
        dc.DrawBitmap(bmap, 0, 30, True)
        #print the text
        if type(self.text) == type(list()):
            f = wx.Font(int(self.font4print), wx.DEFAULT , wx.ITALIC, wx.BOLD)
            dc.SetFont(f)
            dc.SetDeviceOrigin(0,0)
            text_sx = self.text[0]
            text_ce = self.text[1]
            text_dx = self.text[2] + ' -- Pag. ' + str(page) + ' di ' + str(self.pages)
            dim_sx = dc.GetTextExtent(text_sx)[0]
            dim_ce = dc.GetTextExtent(text_ce)[0]
            dim_dx = dc.GetTextExtent(text_dx)[0]
            pos_sx = int(marginX*3)
            pos_ce = int( (maxX / 2) - (dim_ce / 2) )
            pos_dx = int( maxX - ( dim_dx + marginX*3 ) )
            if sys.platform == 'win32':
                marginY = 0
            else:
                marginY = 30
            dc.DrawText(text_sx, pos_sx ,  marginY)
            dc.DrawText(text_ce, pos_ce ,  marginY)
            dc.DrawText(text_dx, pos_dx ,  marginY)
        #Re-set the current worker page
        if self.pages == page:
            self._images.setCurrentPage(self.currentWorkerPage)
        return True

    def HasPage(self, page):
        if page <= self.pages:
            return True
        else:
            return False

    def OnBeginDocument(self, stpg, endpg):
        if not wx.Printout.OnBeginDocument(self, stpg, endpg):
            return False
        return True

class MyApp(wx.App):
    def OnInit(self):
        wx.InitAllImageHandlers()
        if len(sys.argv) > 1:
            self.main = Img_view(None, sys.argv[1:], only4test=1)
        else:
            print "Load me with '%s image'" % sys.argv[0]
            return False
        self.main.Show()
        return True

if __name__ == '__main__':
    app = MyApp(0)
    app.MainLoop()
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.