# ----------------------------------------------------------------------------
#
#  Copyright (C) 2018-2022 Fons Adriaensen <fons@linuxaudio.org>
#    
#  This program 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 3 of the License, or
#  (at your option) any later version.
#
#  This program 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 this program.  If not, see <http:#www.gnu.org/licenses/>.
#
# ----------------------------------------------------------------------------


from PyQt5 import QtWidgets, QtGui, QtCore


# Style class for buttons.
#
class ButtonStyle ():
    
    def __init__(self, sx, sy, bgcol, fgcol, mkcol = None, font = None, pixs = None):
        self.pixmap = ButtonStyle.make_pixmap (sx, sy, bgcol, fgcol)
        self.mkcol = mkcol
        self.nstate = len (fgcol)
        self.dx = self.pixmap.width () // self.nstate
        self.dy = self.pixmap.height ()
        self.font = font
        self.pixs = pixs
        
        
    @classmethod    
    def make_pixmap (cls, sx, sy, bgcol, fgcol):
        nc = len (fgcol)
        sx += 1
        sy += 1
        pm = QtGui.QPixmap (nc * sx, sy);
        pm.fill (bgcol)
        qp = QtGui.QPainter (pm)
        qp.setRenderHint (QtGui.QPainter.Antialiasing)
        sh = QtGui.QColor (0, 0, 0, 180)

        for i in range (nc):
            qp.fillRect (2, 2, sx - 2, sy - 2, sh)
            cg = QtGui.QLinearGradient (0, sy / 2, 0, 0)
            cg.setColorAt (0.0, fgcol [i].darker (110))
            cg.setColorAt (0.6, fgcol [i])
            cg.setColorAt (1.0, fgcol [i].lighter (115))
            qp.fillRect (1, 1, sx - 2, sy - 2, cg)
            qp.translate (sx, 0)
        qp.end ()       
        return pm


# Base class for buttons.
#
class ButtonBase (QtWidgets.QWidget):

    bpressEvent = QtCore.pyqtSignal(object)
    brelseEvent = QtCore.pyqtSignal(object)
    modifiers = None
    mousebutt = None
    
    def __init__(self, parent, style, inpen = False, index = None):
        super (ButtonBase, self).__init__(parent)
        self.resize (style.dx - 1, style.dy - 1)
        self.style = style
        self.inpen = inpen
        self.state = 0
        self.index = index
        self.text = None

    def set_text (self, t):
        if t is None: self.text = t;
        else:
            self.text = t.split ('\n')
            st = self.style
            ft = st.font
            ft.setPixelSize (st.pixs)
            fm = QtGui.QFontMetrics (ft)
            a = fm.ascent ()
            h = fm.descent () + a
            n = len (self.text)
            d = (st.dy - 2 - n * h) / (n + 1)
            self.xt = [(st.dx - fm.width (t) - 2) / 2 for t in self.text] 
            self.yt = a + d 
            self.dy = h + d
        self.update ()
            
    def set_state (self, s):
        s = (s & 255) | (self.state & 256)
        if s != self.state:
            self.state = s
            self.update ()
            
    def get_state (self):
        return self.state & 255
            
    def mousePressEvent (self, E):
        ButtonBase.modifiers = E.modifiers ()
        ButtonBase.mousebutt = E.button()
        if self.inpen:
            self.state |= 256
            self.update ()
            self.bpressEvent.emit (self)
        
    def mouseReleaseEvent (self, E):
        ButtonBase.modifiers = E.modifiers ()
        ButtonBase.mousebutt = E.button()
        if self.inpen:
            self.state &= 255
            self.update ()
            self.brelseEvent.emit (self)
        
    def paintEvent (self, e):
        st = self.style
        pm = st.pixmap
        ks = self.state & 255
        dd = self.state >> 8
        qp = QtGui.QPainter (self)
        qp.drawPixmap (0, 0, pm, ks * st.dx + 1 - dd, 1 - dd, st.dx - 1, st.dy - 1)
        if self.text is not None:
            ft = st.font
            ft.setPixelSize (st.pixs)
            qp.setFont (ft)
            qp.setPen (st.mkcol [ks])
            n = len (self.text)
            y = self.yt + dd
            for i in range (n):
                qp.drawText (QtCore.QPointF (self.xt [i] + dd, y), self.text [i])
                y += self.dy
        qp.end ()

