# ----------------------------------------------------------------------------
#
#  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 rotary controls.
#
class RotaryStyle ():
    
    def __init__(self, rad, bgcol, fgcol, mkcol):
        self.pixmap = RotaryStyle.make_pixmap (rad, bgcol, fgcol, mkcol)
        self.mkcol = mkcol
        self.nstate = len (fgcol)
        self.sx = self.pixmap.width () // self.nstate
        self.sy = self.pixmap.height ()

    @classmethod    
    def make_pixmap (cls, rad, bgcol, fgcol, mkcol):
        nc = len (fgcol)
        r = int (rad)
        s = 2 * r + 5
        pm = QtGui.QPixmap (nc * s, s);
        pm.fill (bgcol)
        qp = QtGui.QPainter (pm)
        qp.translate (s / 2, s / 2)
        qp.setRenderHint (QtGui.QPainter.Antialiasing)
        sh = QtGui.QColor (0, 0, 0, 180)
        for i in range (nc):
            qp.setPen (QtCore.Qt.NoPen)
            qp.setBrush (sh)
            qp.drawEllipse (2 - rad, 2 - rad, 2 * rad, 2 * rad)
            cg = QtGui.QRadialGradient (0, 0, rad, -5, -5, 1)
            cg.setColorAt (1.0, fgcol [i].darker (110))
            cg.setColorAt (0.5, fgcol [i])
            cg.setColorAt (0.0, fgcol [i].lighter (110))
            qp.setBrush (cg)
            qp.drawEllipse (-rad, -rad, 2 * rad, 2 * rad)
            qp.translate (s, 0)
        qp.end ()       
        return pm
        
        
# Base class for rotary controls.
#
class RotaryBase (QtWidgets.QWidget):

    valueEvent = QtCore.pyqtSignal(object)
    pressEvent = QtCore.pyqtSignal(object)
    relseEvent = QtCore.pyqtSignal(object)
    modifiers = None
    mousebutt = None
    xref = 0
    yref = 0
    kref = 0
    
    def __init__(self, parent, style):
        super (RotaryBase, self).__init__(parent)
        self.resize (style.sx, style.sy)
        self.style = style
        self.s = 0
        self.w = 0
        self.k = 0
        self.a = self.k2a (self.k)
        self.v = self.k2v (self.k)

    def get_state (self):
        return self.s
            
    def set_state (self, s):
        self.s = s
        self.update ()
            
    def get_value (self):
        return self.v

    def set_value (self, v):
        self.k = self.v2k (v)
        self.a = self.k2a (self.k)
        self.v = self.k2v (self.k)
        self.update ()
    
    def mousePressEvent (self, E):
        RotaryBase.modifiers = E.modifiers()
        RotaryBase.mousebutt = E.button()
        RotaryBase.kref = self.k
        RotaryBase.xref = E.x ()
        RotaryBase.yref = E.y ()
        self.pressEvent.emit (self)
    
    def mouseReleaseEvent (self, E):
        RotaryBase.modifiers = E.modifiers()
        RotaryBase.mousebutt = E.button()
        self.relseEvent.emit (self)

    def mouseMoveEvent (self, E):
        d = (E.x () - RotaryBase.xref) - (E.y () - RotaryBase.yref)
        self.handle_move (d)
        self.a = self.k2a (self.k)
        self.v = self.k2v (self.k)
        self.update ()
        self.valueEvent.emit (self)
    
    def wheelEvent (self, E):
        RotaryBase.modifiers = E.modifiers ()
        w = self.w + E.angleDelta().y ()
        if abs (w) >= 60:
            self.handle_wheel (w)
            w = 0
        self.w = w    
        self.a = self.k2a (self.k)
        self.v = self.k2v (self.k)
        self.update ()
        self.valueEvent.emit (self)
        
    def paintEvent (self, E):
        st = self.style
        pm = st.pixmap
        s = self.s
        qp = QtGui.QPainter ()
        qp.begin (self)
        qp.setRenderHint (QtGui.QPainter.Antialiasing)
        qp.drawPixmap (0, 0, pm, s * st.sx, 0, st.sx, st.sy)
        qp.setPen (QtGui.QPen (st.mkcol [s], 1.3))
        qp.translate (st.sx / 2, st.sy / 2)
        qp.rotate (-self.a)
        qp.drawLine (0, 0, st.sx // 2 - 3, 0)
        qp.end ()

        
