Logo Search packages:      
Sourcecode: darkroom version File versions

kgradientslider.cc

/*
 *  Copyright (c) 2008 Cyrille Berger <cberger@cberger.net>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser 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 Lesser General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
 
 
#include "kgradientslider.h"

// Qt includes
#include <QPainter>
#include <QPoint>
#include <QPen>
#include <QMouseEvent>

// Local includes.

struct KGradientSlider::Private {
  QColor leftColor;
  QColor rightColor;
  QColor middleColor;
  double leftCursor;
  double middleCursor;
  double rightCursor;
  bool showMiddleCursor;
  KGradientSlider* parent;
  
  int gradientHeight() const
  {
    return parent->height() / 3;
  }
  int cursorWidth() const
  {
    return gradientHeight();
  }
  int gradientWidth() const
  {
    return parent->width() - cursorWidth();
  }
  int gradientOffset() const
  {
    return cursorWidth() / 2;
  }
  enum Cursor {
    NoCursor,
    LeftCursor,
    RightCursor,
    MiddleCursor
  };
  Cursor activeCursor;
};

KGradientSlider::KGradientSlider(QWidget *parent)
            : QWidget(parent), d(new Private)
{
  setMaximumHeight(28);
  d->leftColor = Qt::black;
  d->rightColor = Qt::white;
  d->middleColor.setRgb( (d->leftColor.red() + d->rightColor.red() ) / 2,
                         (d->leftColor.green() + d->rightColor.green() ) / 2,
                         (d->leftColor.blue() + d->rightColor.blue() ) / 2 );
  d->leftCursor = 0.0;
  d->middleCursor = 0.5;
  d->rightCursor = 1.0;
  d->showMiddleCursor = false;
  d->parent = this;
  d->activeCursor = Private::NoCursor;
}

KGradientSlider::~KGradientSlider()
{
}

inline void drawCursorAt( QPainter& _painter, double _pos, const QColor& _brushColor, int _width, int _height, int _gradientWidth )
{
  _painter.setBrush( _brushColor );
  int pos = _gradientWidth * _pos;
  QPoint points[3];
  points[0] = QPoint( pos, 3 * _height - 1);
  points[1] = QPoint( pos + _width / 2, 2 * _height );
  points[2] = QPoint( pos + _width, 3 * _height - 1 );
  _painter.drawPolygon( points, 3 );
}

void KGradientSlider::paintEvent(QPaintEvent *)
{
  int gradientHeight = d->gradientHeight();
  int cursorWidth = d->cursorWidth();
  int gradientWidth = d->gradientWidth();
  int gradientOffset = d->gradientOffset();
  QPainter painter(this);
  // Draw first gradient
  QLinearGradient lrGradient(QPointF(0, 0), QPointF(gradientWidth, 0));
  lrGradient.setColorAt(0.0, d->leftColor );
  lrGradient.setColorAt(1.0, d->rightColor );
  painter.setPen( Qt::NoPen );
  painter.setBrush( lrGradient );
  painter.drawRect(gradientOffset, 0, gradientWidth, gradientHeight );
  
  // Draw second gradient
  QLinearGradient lrcGradient(QPointF(0, 0), QPointF(gradientWidth, 0));
  lrcGradient.setColorAt( d->leftCursor, d->leftColor );
  if( d->showMiddleCursor )
  {
    lrcGradient.setColorAt( d->middleCursor, d->middleColor );
  }
  lrcGradient.setColorAt( d->rightCursor, d->rightColor );
  painter.setBrush( lrcGradient );
  painter.drawRect(gradientOffset, gradientHeight, gradientWidth, gradientHeight );

  // Draw cursors
  painter.setPen( palette().color(QPalette::Text) );
  drawCursorAt( painter, d->leftCursor, d->leftColor, cursorWidth, gradientHeight, gradientWidth );
  if(d->showMiddleCursor)
  {
    drawCursorAt( painter, d->middleCursor, d->middleColor, cursorWidth, gradientHeight, gradientWidth );
  }
  drawCursorAt( painter, d->rightCursor, d->rightColor, cursorWidth, gradientHeight, gradientWidth );
}

inline bool isCursorClicked( const QPoint& _pos, double _cursorPos, int _width, int _height, int _gradientWidth )
{
  int pos = _gradientWidth * _cursorPos;
  return ( _pos.y() >= 2 * _height && _pos.y() < 3 * _height && _pos.x() >= pos && _pos.x() <= (pos + _width) );
}

void KGradientSlider::mousePressEvent ( QMouseEvent * e )
{
  if( e->button() == Qt::LeftButton )
  {
    int gradientHeight = d->gradientHeight();
    int cursorWidth = d->cursorWidth();
    int gradientWidth = d->gradientWidth();
    // Select cursor
    if( isCursorClicked( e->pos(), d->leftCursor , cursorWidth, gradientHeight, gradientWidth ) )
    {
      d->activeCursor = Private::LeftCursor;
    } else if( d->showMiddleCursor && isCursorClicked( e->pos(), d->middleCursor , cursorWidth, gradientHeight, gradientWidth ) )
    {
      d->activeCursor = Private::MiddleCursor;
    } else if( isCursorClicked( e->pos(), d->rightCursor , cursorWidth, gradientHeight, gradientWidth ) )
    {
      d->activeCursor = Private::RightCursor;
    }
  }
}

void KGradientSlider::mouseReleaseEvent ( QMouseEvent * )
{
  d->activeCursor = Private::NoCursor;
}

void KGradientSlider::mouseMoveEvent ( QMouseEvent * e )
{
  double v = ( e->pos().x() - d->gradientOffset() ) / (double) d->gradientWidth();
  switch(d->activeCursor)
  {
    case Private::LeftCursor:
      setLeftValue( v );
      break;
    case Private::MiddleCursor:
      setMiddleValue( v );
      break;
    case Private::RightCursor:
      setRightValue( v );
      break;
    default:
      break;
  }
}

void KGradientSlider::leaveEvent( QEvent * )
{
  d->activeCursor = Private::NoCursor;
}

void KGradientSlider::showMiddleCursor(bool b)
{
  d->showMiddleCursor = b;
}

double KGradientSlider::leftValue() const
{
  return d->leftCursor;
}

double KGradientSlider::rightValue() const
{
  return d->rightCursor;
}

double KGradientSlider::middleValue() const
{
  return d->middleCursor;
}

void KGradientSlider::adjustMiddleValue( double _newLeftValue, double _newRightValue )
{
  double newDist = _newRightValue - _newLeftValue;
  double oldDist = d->rightCursor - d->leftCursor;
  double oldPos = d->middleCursor - d->leftCursor;
  d->middleCursor = oldPos * newDist / oldDist + _newLeftValue;
}

void KGradientSlider::setRightValue(double v) {
  if( v <= 1.0 && v > d->leftCursor && v != d->rightCursor )
  {
    adjustMiddleValue( d->leftCursor, v );
    d->rightCursor = v;
    update();
    emit rightValueChanged(v);
    emit middleValueChanged(d->middleCursor);
  }
}
void KGradientSlider::setLeftValue(double v) {
  if( v >= 0.0 && v != d->leftCursor && v < d->rightCursor )
  {
    adjustMiddleValue( v, d->rightCursor );
    d->leftCursor = v;
    update();
    emit leftValueChanged(v);
    emit middleValueChanged(d->middleCursor);
  }
}
void KGradientSlider::setMiddleValue(double v) {
  if( v > d->leftCursor && v != d->middleCursor && v < d->rightCursor )
  {
    d->middleCursor = v;
    update();
    emit middleValueChanged(v);
  }
}

#include "kgradientslider.moc"

Generated by  Doxygen 1.6.0   Back to index