# PyUI
# Copyright (C) 2001-2002 Sean C. Riley
# 
# This library is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
# 
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
# 
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
import pygame
import pygame.font
import pygame.image
import pygame.key
import pygame.draw
import pyui.core
import pygame.transform

from pygame.locals import *

from pyui.desktop import getDesktop

class renderer2D(pyui.core.RendererBase):
    """Pygame 2D renderer.
    """
    name = "2D"
    
    def __init__(self, w, h, fullscreen):
        pyui.core.RendererBase.__init__(self, w, h, fullscreen)
        pygame.init()
        if fullscreen:
            self.screen = pygame.display.set_mode((w, h), FULLSCREEN | SWSURFACE)
        else:
            self.screen = pygame.display.set_mode((w, h))
        self.screen.set_alpha(255)
            
        pygame.key.set_mods(KMOD_NONE)

        pyui.locals.K_SHIFT     = 304
        pyui.locals.K_CONTROL   = 306
        pyui.locals.K_ALT       = 308

        pyui.locals.K_PAGEUP    = 280
        pyui.locals.K_PAGEDOWN  = 281
        pyui.locals.K_END       = 279
        pyui.locals.K_HOME      = 278

        pyui.locals.K_LEFT      = 276
        pyui.locals.K_UP        = 273
        pyui.locals.K_RIGHT     = 275
        pyui.locals.K_DOWN      = 274

        pyui.locals.K_INSERT    = 277
        pyui.locals.K_DELETE    = 127

        pyui.locals.K_F1        = 282
        pyui.locals.K_F2        = 283
        pyui.locals.K_F3        = 284
        pyui.locals.K_F4        = 285
        pyui.locals.K_F5        = 286
        pyui.locals.K_F6        = 287
        pyui.locals.K_F7        = 288
        pyui.locals.K_F8        = 289
        pyui.locals.K_F9        = 290
        pyui.locals.K_F10       = 291
        pyui.locals.K_F11       = 292
        pyui.locals.K_F12       = 293

        try:
            self.font = pygame.font.Font("font.ttf", 14)
        except:
            print "Couldn't find arial.ttf - resorting to default font"
            self.font = pygame.font.Font(None, 12)
        pyui.locals.TEXT_HEIGHT = self.font.get_height()
        self.lastID = 1000
        self.windows = {}
        self.images = {}

    def doesDirtyRects(self):
        return 1


    def draw(self, windows):
        #self.screen.set_clip( (0,0,self.w, self.h))
        self.screen.fill((0,0,0, 255))
            
        for i in xrange(len(windows)-1, -1, -1):
            w = windows[i]
            w.setDirty(1)
            n =  w.drawWindow(self)
            if n:
                self.windowPos = (w.posX, w.posY)
                for command in w.drawCommands:
                    self.doDrawCommand(command)

        if self.mustFill:
            pygame.display.flip()
        else:
            pygame.display.update()#self.dirtyRects)

        self.mustFill = 0
        self.dirtyRects = []


    ###############################################################################
    ### Draw Primatives functions
    ###############################################################################
        
    def drawRect(self, color, rect):
        """Fills a rectangle with the specified color."""
        self.drawList.append( (pyui.locals.RECT, rect, color) )

    def drawText(self, text, pos, color, font = None):
        """Draws the text on the screen in the specified position"""
        self.drawList.append( (pyui.locals.TEXT, text, pos, color) )

    def drawGradient(self, rect, c1, c2, c3, c4):
        """Draws a gradient rectangle"""
        self.drawList.append( (pyui.locals.GRADIENT, rect, c1, c2, c3, c4 ) )

    def drawImage(self, rect, filename):
        """Draws an image at a position"""
        if not self.images.has_key(filename):
            self.loadImage(filename)
        self.drawList.append( (pyui.locals.IMAGE, rect, filename) )

    def drawLine(self, x1, y1, x2, y2, color):
        """Draws a line"""
        self.drawList.append( (pyui.locals.LINE, x1, y1, x2, y2, color) )

    def loadImage(self, filename, label = None):
        if label:
            self.images[label] = pygame.image.load(filename)
        else:
            self.images[filename] = pygame.image.load(filename)            

    def setClipping(self, rect = None):
        """set the clipping rectangle for the main screen. defaults to clearing the clipping rectangle."""
        self.drawList.append( (pyui.locals.CLIP, rect) )

    ###############################################################################
    ### actual drawing functions
    ###############################################################################

    def doDrawCommand(self, command):
        cmd = command[0]
        if cmd == pyui.locals.RECT:
            (cmd, rect, color) = command
            #print "pyui.locals.RECT: " ,command[1], command[2]
            rect = (self.windowPos[0]+rect[0], self.windowPos[1]+rect[1], rect[2], rect[3])
            self.screen.fill(color, rect)
            return 2
        elif cmd == pyui.locals.TEXT:
            (cmd, text, pos, color) = command
            if not text:
                return
            pos = (self.windowPos[0]+pos[0], self.windowPos[1]+pos[1])
            surf = self.font.render(text, 0, color, (0,0,0,255)) 
            surf.set_colorkey( (0,0,0,255))
            self.screen.blit(surf, pos)
            return len(text)
        elif cmd == pyui.locals.IMAGE:
            (cmd, rect, filename) = command
            rect = (self.windowPos[0]+rect[0], self.windowPos[1]+rect[1], rect[2], rect[3])
            img = self.images[filename]
            (w,h) = img.get_size()
            if (w,h) != (rect[2], rect[3]):
                img = pygame.transform.scale(img, (rect[2], rect[3]) )
            self.screen.blit(img, (rect[0], rect[1]) )
            return 2
        elif cmd == pyui.locals.GRADIENT:
            (cmd, rect, c1, c2, c3, c4 ) = command
            rect = (self.windowPos[0]+rect[0], self.windowPos[1]+rect[1], rect[2], rect[3])
            self.screen.fill(c3, rect)            
            return 2
        elif cmd == pyui.locals.CLIP:
            #(cmd, rect) = command
            #rect = (self.windowPos[0]+rect[0], self.windowPos[1]+rect[1], rect[2], rect[3])
            #self.screen.set_clip(rect)
            pass
        elif cmd == pyui.locals.LINE:
            (pyui.locals.LINE, x1, y1, x2, y2, color) = command
            pos1 = (self.windowPos[0] + x1, self.windowPos[1] + y1)
            pos2 = (self.windowPos[0] + x2, self.windowPos[1] + y2)
            pygame.draw.line(self.screen, color, pos1, pos2)
        return 0
        

    def update(self):
        ## process all pending system events.
        event = pygame.event.poll()
        while event.type != NOEVENT:
            
            # special case to handle multiple mouse buttons!
            if event.type == MOUSEBUTTONDOWN:
                if event.dict['button'] == 1:
                    getDesktop().postUserEvent(pyui.locals.LMOUSEBUTTONDOWN, event.pos[0], event.pos[1])
                elif event.dict['button'] == 3:
                    getDesktop().postUserEvent(pyui.locals.RMOUSEBUTTONDOWN, event.pos[0], event.pos[1])
                    
            elif event.type == MOUSEBUTTONUP:
                if event.dict['button'] == 1:
                    getDesktop().postUserEvent(pyui.locals.LMOUSEBUTTONUP, event.pos[0], event.pos[1])
                elif event.dict['button'] == 3:
                    getDesktop().postUserEvent(pyui.locals.RMOUSEBUTTONUP, event.pos[0], event.pos[1])
                    
            elif event.type == MOUSEMOTION:
                getDesktop().postUserEvent(pyui.locals.MOUSEMOVE, event.pos[0], event.pos[1])

            elif event.type == KEYDOWN:
                character = event.unicode
                code = 0
                if len(character) > 0:
                    code = ord(character)
                else:
                    code = event.key
                getDesktop().postUserEvent(pyui.locals.KEYDOWN, 0, 0, code, pygame.key.get_mods())
                if code >= 32 and code < 128:
                    getDesktop().postUserEvent(pyui.locals.CHAR, 0, 0, character.encode(), pygame.key.get_mods())

            elif event.type == KEYUP:
                code = event.key
                getDesktop().postUserEvent(pyui.locals.KEYUP, 0, 0, code, pygame.key.get_mods())
            else:
                try:
                    getDesktop().postUserEvent(event.type)
                except:
                    print "Error handling event %s" % repr(event)
            event = pygame.event.poll()


    def quit(self):
        pygame.quit()


    def packColor(self, r, g, b, a = 255):
        """pack the rgb triplet into a color
        """
        return (r, g, b, a)

    def getTextSize(self, text, font = None):
        return self.font.size(text)
