#!/usr/bin/python

#   Copyright (C) 2002-2003 Yannick Gingras <ygingras@ygingras.net>
#   Copyright (C) 2002-2003 Vincent Barbin <vbarbin@openbeatbox.org>

#   This file is part of Open Beat Box.

#   Open Beat Box is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.

#   Open Beat Box 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 General Public License for more details.

#   You should have received a copy of the GNU General Public License
#   along with Open Beat Box; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

from qt import *
from PixmapSet    import *
from StretchFrame import StretchFrame
from OBBConstants import LEFT, RIGHT, CENTER, SCROLL, RL_SCROLL, LR_SCROLL
from unicodedata  import bidirectional


class OBBLabel(StretchFrame):
    def __init__( self,
                  pixmapSet,
                  parent=None,
                  x=0,
                  y=0,
                  stretchPoint=30,
                  stretchSize=50,
                  wantedSize=100,
                  borderX = 5,
                  borderY = 7,
                  fontSize = 12,
                  align = LEFT):
        StretchFrame.__init__( self,
                               pixmapSet,
                               parent,
                               x,
                               y,
                               "x",
                               stretchPoint,
                               stretchSize,
                               wantedSize )
        self.borderX = borderX
        self.borderY = borderY
        self.fontSize = fontSize
        self.font = QFont()
        self.font.setPixelSize(self.fontSize)
        self.font.setWeight(75)
        self.font.setFamily("Helvetica")
        self.fontMetrics = QFontMetrics(self.font)
        self.scrollOffset = -1 # because of the shadow
        self.curText = """Welcome to OBB !"""
        self.curText += " " * 75
        self.align = align


    def paintCurPixmapXY( self,
                          x,
                          y,
                          width,
                          height,
                          globalX,
                          globalY,
                          paintDev ):
        statePix = self.pixmapSet.getState(self.curState)

        globalPosX = globalX + self.x
        globalPosY = globalY + self.y
        
        paintDev.drawPixmap( x+globalPosX,
                             y+globalPosY,
                             statePix,
                             x,
                             y,
                             width,
                             height )

        oldRegion = None
        if paintDev.hasClipping():
            oldRegion = paintDev.clipRegion()

        paintDev.setClipRect( globalPosX+self.borderX,
                              globalPosY+self.borderY/2,
                              self.width()-(self.borderX*2),
                              self.height()-(self.borderY) )
        oldPen = paintDev.pen()
        oldRop = paintDev.rasterOp()
        paintDev.setFont(self.font)
        paintDev.setPen(Qt.darkGray)
        paintDev.setRasterOp(Qt.AndROP)
        paintDev.drawText( globalPosX+self.borderX-self.scrollOffset,
                           globalPosY+self.height()-self.borderY,
                           self.curText )
        paintDev.setRasterOp(oldRop)

        paintDev.setPen(Qt.black)
        paintDev.drawText( globalPosX+self.borderX-self.scrollOffset-1,
                           globalPosY+self.height()-self.borderY-1,
                           self.curText )

        paintDev.setPen(oldPen)


        if oldRegion:
            paintDev.setClipRegion(oldRegion)
        else:
            paintDev.setClipping(0)

        for widget in self.subWidgets:
            ( isIn,
              invalidRectX,
              invalidRectY,
              invalidRectX2,
              invalidRectY2 ) = widget.getIntersection(x, y, width, height)
            if isIn:
                widgetRect = widget.curBoundingRect

                invalidRectWidth  = invalidRectX2 - invalidRectX
                invalidRectHeight = invalidRectY2 - invalidRectY
        
                widget.paintCurPixmapXY( invalidRectX - widget.x,
                                         invalidRectY - widget.y,
                                         invalidRectWidth,
                                         invalidRectHeight,
                                         globalPosX,
                                         globalPosY,
                                         paintDev )


    def rlScroll(self):
        self.scrollOffset = self.scrollOffset + 1
        if self.scrollOffset >= self.getCharWidth(self.curText):
            self.scrollOffset = 0
            self.curText = self.curText[1:] + self.curText[:1]        


    def lrScroll(self):
        self.scrollOffset = self.scrollOffset - 1
        if self.scrollOffset <= 0:
            self.curText = self.curText[-1:] + self.curText[:-1]
            self.scrollOffset = self.getCharWidth(self.curText)


    def scroll(self):
        align = self.align
        if align == SCROLL:
            # find the right align acording to presented text
            align = self.findTextDirection()
        if align == RL_SCROLL:
            self.rlScroll()
        elif align == LR_SCROLL:
            self.lrScroll()
        else:
            return # can only scroll horizontally  : (
            
        self.parent().repaintWidget(self, self.region)


    def findTextDirection(self):
        # see http://www.unicode.org/Public/UNIDATA/UCD.html#Bidi_Class_Values
        for char in self.curText:
            if bidirectional(unicode(char)) in ["L", "LRE", "LRO"]:
                # written left to right; scroll right to left
                return RL_SCROLL
            elif bidirectional(unicode(char)) in ["R", "AL", "RLE", "RLO"]:
                # written ...; ...
                return LR_SCROLL
            else:
                pass # this one was non-directional, try the next one
            
        # default
        return RL_SCROLL


    def setText(self, text):
        # self.width() is not reliable since derived class (ie. OBBSpinBox)
        # might end up larger that the text zone
        imgWidth = self.pixmapSet.getState(DISABLED).width()
        self.curText = text
        scratchPadWidth = imgWidth - (self.borderX * 2)
        textWidth = self.fontMetrics.width(text)
        
        if self.align == LEFT:
            self.scrollOffset = -1 # the shadow takes 1
        elif self.align == RIGHT:
            self.scrollOffset = -(scratchPadWidth - textWidth)
        elif self.align == CENTER:
            self.scrollOffset = -((scratchPadWidth - textWidth) / 2)
        else:
            pass # might be on scroll mode so let it move
        self.parent().repaintWidget(self, self.region)        


    def getCharWidth(self, str, pos=0):
        try:
            return self.fontMetrics.charWidth(str, pos)
        except AttributeError:
            # probably on Qt 2.x ...
            return self.fontMetrics.width(str[pos])
