/*****************************************************************************
*
* Copyright (c) 2000 - 2007, The Regents of the University of California
* Produced at the Lawrence Livermore National Laboratory
* All rights reserved.
*
* This file is part of VisIt. For details, see http://www.llnl.gov/visit/. The
* full copyright notice is contained in the file COPYRIGHT located at the root
* of the VisIt distribution or at http://www.llnl.gov/visit/copyright.html.
*
* Redistribution  and  use  in  source  and  binary  forms,  with  or  without
* modification, are permitted provided that the following conditions are met:
*
*  - Redistributions of  source code must  retain the above  copyright notice,
*    this list of conditions and the disclaimer below.
*  - Redistributions in binary form must reproduce the above copyright notice,
*    this  list of  conditions  and  the  disclaimer (as noted below)  in  the
*    documentation and/or materials provided with the distribution.
*  - Neither the name of the UC/LLNL nor  the names of its contributors may be
*    used to  endorse or  promote products derived from  this software without
*    specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT  HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR  IMPLIED WARRANTIES, INCLUDING,  BUT NOT  LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS FOR A PARTICULAR  PURPOSE
* ARE  DISCLAIMED.  IN  NO  EVENT  SHALL  THE  REGENTS  OF  THE  UNIVERSITY OF
* CALIFORNIA, THE U.S.  DEPARTMENT  OF  ENERGY OR CONTRIBUTORS BE  LIABLE  FOR
* ANY  DIRECT,  INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT  LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR
* SERVICES; LOSS OF  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER
* CAUSED  AND  ON  ANY  THEORY  OF  LIABILITY,  WHETHER  IN  CONTRACT,  STRICT
* LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY  WAY
* OUT OF THE  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*****************************************************************************/

#include "QvisAbstractOpacityBar.h"
#include "ColorControlPointList.h"

#include <qimage.h>
#include <qpainter.h>
#include <qpixmap.h>
#include <qpolygon.h>

#include <cmath>
#include <cstdlib>
#include <iostream>

// ****************************************************************************
//  Method:  QvisAbstractOpacityBar::QvisAbstractOpacityBar
//
//  Purpose:
//
//
//  Programmer:  Jeremy Meredith
//  Creation:    January 31, 2001
//
// ****************************************************************************

QvisAbstractOpacityBar::QvisAbstractOpacityBar(QWidget* parentObject, const char* /*name*/)
  : QFrame(parentObject)
{
  setFrameStyle(QFrame::Panel | QFrame::Sunken);
  setLineWidth(2);
  setMinimumHeight(50);
  setMinimumWidth(128);
  pix = new QPixmap;
  backgroundColorControlPoints = 0;
  backgroundPixmap = NULL;
}

// ****************************************************************************
//  Method:  QvisAbstractOpacityBar::~QvisAbstractOpacityBar
//
//  Purpose:
//
//
//  Programmer:  Jeremy Meredith
//  Creation:    January 31, 2001
//
//  Modifications:
//    Brad Whitlock, Thu Feb 14 13:19:19 PST 2002
//    Deleted pix.
//
// ****************************************************************************

QvisAbstractOpacityBar::~QvisAbstractOpacityBar()
{
  delete pix;
  delete backgroundColorControlPoints;
  pix = 0;
  showBackgroundPixmap = false;
}

void QvisAbstractOpacityBar::SetShowBackgroundPixmap(bool showFlag)
{
  showBackgroundPixmap = showFlag;
}

// ****************************************************************************
//  Method:  QvisAbstractOpacityBar::SetBackgroundColorControlPoints(const ColorControlPointList
//  *ccp)
//
//  Purpose: Set color control points for color transfer function backdrop
//
//
//  Programmer:  Gunther H. Weber
//  Creation:    April 5, 2007
//
//  Modifications:
//
// ****************************************************************************

void QvisAbstractOpacityBar::SetBackgroundColorControlPoints(
  const pointsprite::ColorControlPointList* ccp)
{
  if (backgroundColorControlPoints)
    delete backgroundColorControlPoints;
  backgroundColorControlPoints = NULL;
  if (ccp)
  {
    backgroundColorControlPoints = new pointsprite::ColorControlPointList(*ccp);
  }
  this->update();
}

void QvisAbstractOpacityBar::SetBackgroundPixmap(QPixmap* background)
{
  if (this->backgroundPixmap)
    delete this->backgroundPixmap;
  this->backgroundPixmap = NULL;
  if (background)
  {
    this->backgroundPixmap = new QPixmap(*background);
  }
}

void QvisAbstractOpacityBar::paintBackground(QPainter& painter, int w, int h)
{
  if (this->showBackgroundPixmap && this->backgroundPixmap)
  {
    painter.drawPixmap(0, 0, *this->backgroundPixmap);
  }
  /*
    else if (backgroundColorControlPoints && backgroundColorControlPoints->GetNumControlPoints()>1)
    {
      unsigned char *cols = new unsigned char[w*3];
      backgroundColorControlPoints->GetColors(cols, w);
      for (int x=0; x<w; ++x) {
        QRgb bgCols = QColor(cols[x*3+0], cols[x*3+1], cols[x*3+2]).rgb();
        painter.setPen(bgCols);
        painter.drawLine(x,0, x, h-1);
      }
      delete[] cols;
    }
  */
  else
  {
    painter.fillRect(0, 0, w, h, QBrush(Qt::black));
  }
}

// ****************************************************************************
//  Method:  QvisAbstractOpacityBar::val2x
//
//  Purpose:
//
//
//  Programmer:  Jeremy Meredith
//  Creation:    January 31, 2001
//
// ****************************************************************************
int QvisAbstractOpacityBar::val2x(float val)
{
  QRect c = contentsRect();
  int w = c.width();
  int l = c.left();
  int _x = int(val * float(w) + l);
  _x = qMax(l, qMin(l + w, _x));
  return _x;
}

// ****************************************************************************
//  Method:  QvisAbstractOpacityBar::x2val
//
//  Purpose:
//
//
//  Programmer:  Jeremy Meredith
//  Creation:    January 31, 2001
//
// ****************************************************************************
float QvisAbstractOpacityBar::x2val(int _x)
{
  QRect c = contentsRect();
  int w = c.width();
  int l = c.left();
  float val = float(_x - l) / float(w);
  val = qMax((float)0, qMin((float)1, val));
  return val;
}

// ****************************************************************************
//  Method:  QvisAbstractOpacityBar::val2y
//
//  Purpose:
//
//
//  Programmer:  Jeremy Meredith
//  Creation:    January 31, 2001
//
// ****************************************************************************
int QvisAbstractOpacityBar::val2y(float val)
{
  QRect c = contentsRect();
  int h = c.height();
  int t = c.top();
  int _y = int((1 - val) * float(h) + t);
  _y = qMax(t, qMin(t + h, _y));
  return _y;
}

// ****************************************************************************
//  Method:  QvisAbstractOpacityBar::y2val
//
//  Purpose:
//
//
//  Programmer:  Jeremy Meredith
//  Creation:    January 31, 2001
//
// ****************************************************************************
float QvisAbstractOpacityBar::y2val(int _y)
{
  QRect c = contentsRect();
  int h = c.height();
  int t = c.top();
  float val = float(_y - t) / float(h);
  val = qMax((float)0, qMin((float)1, ((float)1 - val)));
  return val;
}

// ****************************************************************************
//  Method:  QvisAbstractOpacityBar::paintEvent
//
//  Purpose:
//
//
//  Programmer:  Jeremy Meredith
//  Creation:    January 31, 2001
//
// ****************************************************************************
void QvisAbstractOpacityBar::paintEvent(QPaintEvent* e)
{
  QFrame::paintEvent(e);
  if (!pix)
    return;
  //
  QPainter painter(this);
  this->paintToPixmap(contentsRect().width(), contentsRect().height());
  painter.drawPixmap(contentsRect().left(), contentsRect().top(), *pix);
  painter.end();
}

// ****************************************************************************
//  Method:  QvisAbstractOpacityBar::resizeEvent
//
//  Purpose:
//
//
//  Programmer:  Jeremy Meredith
//  Creation:    January 31, 2001
//
// ****************************************************************************
void QvisAbstractOpacityBar::resizeEvent(QResizeEvent*)
{
  QRect framerect(rect());
  framerect.setTop(framerect.top() + 5);
  framerect.setBottom(framerect.bottom() - 5);
  framerect.setLeft(framerect.left() + 13);
  framerect.setRight(framerect.right() - 13);
  setFrameRect(framerect);

  int w = contentsRect().width();
  int h = contentsRect().height();

  delete pix;
  pix = new QPixmap(w, h);

  emit resized();
}
