// $Id: lprofgauge.cpp,v 1.2 2008/02/19 21:02:39 hvengel Exp $
//  Little cms Profiler
// Copyright (C) 2008 Hal Engel
//
// THIS SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
// EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
// WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
//
// IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
// INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
// OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
// LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
// OF THIS SOFTWARE.
//
// 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/>.
//
// Version 1.11

// This is derived from the following authors work which has be heavily 
// modified.

/***************************************************************************
 *   Copyright (C) 2008 by P. Sereno                                       *
 *   http://www.sereno-online.com                                          *
 *   http://www.qt4lab.org                                                 *
 *   http://www.qphoton.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 2 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, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
  
#include <QColor>
#include <QtGlobal>
#include <QtGui>
#include <QPolygon>


#include "lprofgauge.h"

LProfGauge::LProfGauge(QWidget *parent)
    : QWidget(parent)
{
   setFocusPolicy(Qt::StrongFocus);
   m_numTicks=1;
   m_precision=1;
   m_value=0;
   markerColor = QColor(255, 255, 255, 255);
   setMinimumSize(QSize(10,180));   
}

void LProfGauge::setColor(QColor color)
{
    markerColor = color;
}

void LProfGauge::paintEvent(QPaintEvent *)
{
    QColor lineColor = Qt::black;
    int x1 = -275;
    int x2 = 275;
    int vSize = 485; 
    int negSize = -485;
    
    int backX1 = -500;
    int backX2 = 500;
    int backTop = 499;
    int backBottom = -499;
    
    QPainter painter(this);
    
    painter.setWindow( -500,-500,1000,1000);
    
    QPolygon a(4);
    //QPen pen(QColor(70,70,70));
    a.setPoint(0,backX1, backBottom);
    a.setPoint(1,backX2, backBottom);
    a.setPoint(2,backX2, backTop);
    a.setPoint(3,backX1, backTop);	
	  
    QLinearGradient linearGrad3(QPointF(backX1, backTop), QPoint(backX2, backBottom));
    linearGrad3.setStart (0, backTop); 
    linearGrad3.setFinalStop(0, backBottom);
    linearGrad3.setColorAt(1, Qt::black);
    linearGrad3.setColorAt(0.75, Qt::black);
    linearGrad3.setColorAt(0.7, QColor(210,0,0,255));
    linearGrad3.setColorAt(0.65, QColor(210,100,0,255)); 
    linearGrad3.setColorAt(0.6, QColor(200,200,0,255));	
    linearGrad3.setColorAt(0.57, QColor(200,215,0,255));
    linearGrad3.setColorAt(0.54, QColor(150,215,0,255));
    	
    linearGrad3.setColorAt(0.503, QColor(0,215,0,255));
    linearGrad3.setColorAt(0.50, QColor(0,0,0,255));
    linearGrad3.setColorAt(0.497, QColor(0,215,0,255));
    
    linearGrad3.setColorAt(0.46, QColor(150,215,0,255));
    linearGrad3.setColorAt(0.43, QColor(200,215,0,255));
    linearGrad3.setColorAt(0.4, QColor(200,200,0,255));
    linearGrad3.setColorAt(0.35, QColor(210,100,0,255));
    linearGrad3.setColorAt(0.30, QColor(210,0,0,255));
    linearGrad3.setColorAt(0.25, Qt::black);
    linearGrad3.setColorAt(0, Qt::black);
     	    
    QBrush brush3(linearGrad3);
    painter.setBrush(brush3); 	
    painter.drawPolygon(a);
    
/*    QPen linePen (lineColor, 3, Qt::SolidLine );	

    painter.setPen(linePen);
    painter.drawLine(0, height()/2, width(), height()/2);*/
    
    QPen pen(Qt::SolidLine);
	painter.setPen(pen);
    if(m_orientation==Horizontal)
        painter.rotate(90.0);
	
    a.setPoint(0,x1, negSize);
    a.setPoint(1,x2, negSize);
    a.setPoint(2,x2, vSize);
    a.setPoint(3,x1, vSize);	
	  
    QLinearGradient linearGrad(QPointF(x1, negSize), QPoint(x2, negSize));
    linearGrad.setColorAt(0, QColor(160,160,160));
    linearGrad.setColorAt(0.35, QColor(50,50,50));
    linearGrad.setColorAt(0.7, QColor(90,90,90)); 		
    linearGrad.setColorAt(1, QColor(30,30,30)); 		
            
    QBrush brush(linearGrad);
    painter.setBrush(brush); 	
    painter.drawPolygon(a);

    bool alarm=false;
    if(m_value>m_alarmThreshold &&m_alarmEnabled)
    {	
    	emit thresholdAlarm(true);
    	alarm=true;
    }	
    if(m_value<=m_alarmThreshold &&m_alarmEnabled)
    	emit thresholdAlarm(false);


    if(m_alarmThreshold!=0.0 &&m_alarmEnabled)
    {	
        int threshold_h=(int)(-450+900*((m_alarmThreshold-m_maxValue)/(m_minValue-m_maxValue)));
        QPolygon th(3);
        th.setPoint(0,0,threshold_h-30);
        th.setPoint(1,80,threshold_h);
        th.setPoint(2,0,threshold_h+30);
    
        if(alarm)
            painter.setBrush(QBrush(Qt::red)); 
        else
            painter.setBrush(QBrush(Qt::green)); 
        painter.drawPolygon(th);    
    }
    

    int h=(int)(-452+900*((m_value-m_maxValue)/(m_minValue-m_maxValue)));

    a.setPoint(0,x1,h);
    a.setPoint(1,x2,h);
    a.setPoint(2,x2, vSize);
    a.setPoint(3,x1, vSize);
    
    bool red, green, blue, gray;
    int max = markerColor.red();
    
    if (markerColor.green() == markerColor.red() && markerColor.red() == markerColor.blue())
        gray = true;
    else
    {
        red = true;
        if (markerColor.green() > markerColor.red())
        {
            green = true;
            max = markerColor.green();
        }
        if (markerColor.blue() > max)
        {
            blue = true;
            max = markerColor.blue();
        } 
    }   
	  
    QLinearGradient linearGrad2(QPointF(x1, negSize), QPoint(x2, negSize));
    if (gray)
        linearGrad2.setColorAt(0, QColor(160, 160, 160));
    else if (red)
        linearGrad2.setColorAt(0, QColor(max, 160, 160));
    else if (green)
        linearGrad2.setColorAt(0, QColor(160, max, 160));
    else
        linearGrad2.setColorAt(0, QColor(160, 160, max));
    linearGrad2.setColorAt(0.15, markerColor);
    linearGrad2.setColorAt(0.35, QColor((int) (markerColor.red() * 0.8), (int) (markerColor.green() * 0.8), (int) (markerColor.blue() * 0.8)));
    linearGrad2.setColorAt(0.7, markerColor);
    linearGrad2.setColorAt(0.95, QColor((int) (markerColor.red() * 0.5), (int) (markerColor.green() * 0.5), (int) (markerColor.blue() * 0.5))); 
    linearGrad2.setColorAt(0.99, QColor((int) (markerColor.red() * 0.35), (int) (markerColor.green() * 0.35), (int) (markerColor.blue() * 0.35)));
    linearGrad2.setColorAt(1, QColor((int) (markerColor.red() * 0.20), (int) (markerColor.green() * 0.20), (int) (markerColor.blue() * 0.20)));			
            
    QBrush brush2(linearGrad2);
    painter.setBrush(brush2); 	
    painter.drawPolygon(a);
	
}


void LProfGauge::mousePressEvent(QMouseEvent *e)
{
    int x=e->x();
    int y=e->y();
    
    int px=(int)(-450 +(900/width())*x);
    int py=(int)(-450 +(900/height())*y);
    
    int threshold_h=(int)(0.9*height()*((m_alarmThreshold-m_maxValue)/(m_minValue-m_maxValue)));
    
    double threshold_d=(double)threshold_h/100;
    threshold_h=(int)(-450+900*threshold_d); 
    
    
    
    //if(py < threshold_h+50 && y >threshold_h-50)
    if(px>0 && px<100)
    {	
      mousePressX=x;
      mousePressY=y;
    }
    else
    {	
      mousePressX=-1;
      mousePressY=-1;
    }
}

void LProfGauge::mouseMoveEvent(QMouseEvent *e)
{
	double delta;
    if(	mousePressY<0)
    {	
      return;
    }
		
    int x=e->x();
    int y=e->y();
    
    
    delta=mousePressY-y;
    delta=delta/(double)height();
    delta=delta*(m_maxValue-m_minValue);
    
    
    m_alarmThreshold=m_alarmThreshold+delta;
    if(m_alarmThreshold<m_minValue)
            m_alarmThreshold=m_minValue;
    if(m_alarmThreshold>m_maxValue)
            m_alarmThreshold=m_maxValue;
            
    mousePressX=x;
    mousePressY=y;
    update();
}


void LProfGauge::mouseReleaseEvent(QMouseEvent *e)
{
      mousePressX=-1;
      mousePressY=-1;  
}



void LProfGauge::setOrientation(GaugeOrientation value)
{
   m_orientation=value;
   update();
}



void LProfGauge::setValue(double value)
{
    if(value<m_minValue)
   	m_value=m_minValue;
   else
   	if(value>m_maxValue)
            m_value=m_maxValue;
   	else 	
            m_value=(double)value;
   update();
}


void LProfGauge::setValue(int value)
{
 setValue((double)value);
}


void LProfGauge::setMinValue(double value)
{
   m_minValue=value;
   update();
}



void LProfGauge::setMaxValue(double value)
{
   m_maxValue=value;
   update();
}


void LProfGauge::enableAlarm(bool alarmEnable)
{
   m_alarmEnabled=alarmEnable;
   update();
}


void LProfGauge::setAlarmThreshold(double threshold)
{
   if(threshold<m_minValue)
     threshold=m_minValue;
   if(threshold>m_maxValue)
     threshold=m_maxValue;
   m_alarmThreshold=threshold;
   update();
}


void LProfGauge::setAlarmThreshold(int threshold)
{
     setAlarmThreshold((double)threshold);	
}


void LProfGauge::setNumTicks(int numTicks)
{
    if(numTicks>1)
        m_numTicks=numTicks;
    update();
}


void LProfGauge::setPrecision(int precision)
{
    if(precision>=0 && precision < 6)
        m_precision=precision;
    update();
}
