You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/chalk/plugins/filters/levelfilter/kgradientslider.cc

339 lines
9.8 KiB

/*
* This file is part of Chalk
*
* Copyright (c) 2006 Frederic Coiffier <fcoiffie@gmail.com>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// C++ includes.
#include <cmath>
#include <cstdlib>
// TQt includes.
#include <tqpixmap.h>
#include <tqpainter.h>
#include <tqpoint.h>
#include <tqpen.h>
// Local includes.
#include "kgradientslider.h"
KGradientSlider::KGradientSlider(TQWidget *parent, const char *name, WFlags f)
: TQWidget(parent, name, f)
{
m_dragging = false;
setMouseTracking(true);
setPaletteBackgroundColor(TQt::NoBackground);
setMaximumSize(255, 28);
m_blackcursor = 0;
m_whitecursor = 255;
m_gamma = 1.0;
m_gammaEnabled = false;
setFocusPolicy(TQ_StrongFocus);
}
KGradientSlider::~KGradientSlider()
{
}
void KGradientSlider::paintEvent(TQPaintEvent *)
{
int x, y;
int wWidth = width();
int wHeight = height();
int gradientHeight = (wHeight / 3);
// A TQPixmap is used for enable the double buffering.
/*if (!m_dragging) {*/
TQPixmap pm(size());
TQPainter p1;
p1.begin(TQT_TQPAINTDEVICE(&pm), this);
pm.fill();
// Draw first gradient
y = 0;
p1.setPen(TQPen(TQColor(0,0,0),1, TQt::SolidLine));
for( x=0; x<255; ++x )
{
int gray = (255 * x) / wWidth;
p1.setPen(TQColor(gray, gray, gray));
p1.drawLine(x, y, x, y + gradientHeight - 1);
}
// Draw second gradient
y = (wHeight / 3);
if (m_blackcursor > 0) {
p1.fillRect(0, y, (int)m_blackcursor, gradientHeight, TQBrush(TQt::black));
}
if (m_whitecursor < 255) {
p1.fillRect((int)m_whitecursor, y, 255, gradientHeight, TQBrush(TQt::white));
}
for(x = (int)m_blackcursor; x < (int)m_whitecursor; ++x )
{
double inten = (double)(x - m_blackcursor) / (double)(m_whitecursor - m_blackcursor);
inten = pow (inten, (1.0 / m_gamma));
int gray = (int)(255 * inten);
p1.setPen(TQColor(gray, gray, gray));
p1.drawLine(x, y, x, y + gradientHeight - 1);
}
// Draw cursors
y = (2 * wHeight / 3);
TQPointArray *a = new TQPointArray(3);
p1.setPen(TQt::black);
a->setPoint(0, m_blackcursor, y);
a->setPoint(1, m_blackcursor + 3, wHeight - 1);
a->setPoint(2, m_blackcursor - 3, wHeight - 1);
p1.setBrush(TQt::black);
p1.drawPolygon(*a);
if (m_gammaEnabled) {
a->setPoint(0, m_gammacursor, y);
a->setPoint(1, m_gammacursor + 3, wHeight - 1);
a->setPoint(2, m_gammacursor - 3, wHeight - 1);
p1.setBrush(TQt::gray);
p1.drawPolygon(*a);
}
a->setPoint(0, m_whitecursor, y);
a->setPoint(1, m_whitecursor + 3, wHeight - 1);
a->setPoint(2, m_whitecursor - 3, wHeight - 1);
p1.setBrush(TQt::white);
p1.drawPolygon(*a);
p1.end();
bitBlt(this, 0, 0, &pm);
}
void KGradientSlider::mousePressEvent ( TQMouseEvent * e )
{
eCursor closest_cursor;
int distance;
if (e->button() != Qt::LeftButton)
return;
unsigned int x = e->pos().x();
distance = 1000; // just a big number
if (abs((int)(x - m_blackcursor)) < distance)
{
distance = abs((int)(x - m_blackcursor));
closest_cursor = BlackCursor;
}
if (abs((int)(x - m_whitecursor)) < distance)
{
distance = abs((int)(x - m_whitecursor));
closest_cursor = WhiteCursor;
}
if (m_gammaEnabled && (abs((int)(x - m_gammacursor)) < distance))
{
distance = abs((int)(x - m_gammacursor));
closest_cursor = GammaCursor;
}
if (distance > 20)
{
return;
}
m_dragging = true;
// Determine cursor values and the leftmost and rightmost points.
switch (closest_cursor) {
case BlackCursor:
m_blackcursor = x;
m_grab_cursor = closest_cursor;
m_leftmost = 0;
m_rightmost = m_whitecursor;
if (m_gammaEnabled) {
double delta = (double) (m_whitecursor - m_blackcursor) / 2.0;
double mid = (double)m_blackcursor + delta;
double tmp = log10 (1.0 / m_gamma);
m_gammacursor = (unsigned int)tqRound(mid + delta * tmp);
}
break;
case WhiteCursor:
m_whitecursor = x;
m_grab_cursor = closest_cursor;
m_leftmost = m_blackcursor;
m_rightmost = 255;
if (m_gammaEnabled) {
double delta = (double) (m_whitecursor - m_blackcursor) / 2.0;
double mid = (double)m_blackcursor + delta;
double tmp = log10 (1.0 / m_gamma);
m_gammacursor = (unsigned int)tqRound(mid + delta * tmp);
}
break;
case GammaCursor:
m_gammacursor = x;
m_grab_cursor = closest_cursor;
m_leftmost = m_blackcursor;
m_rightmost = m_whitecursor;
double delta = (double) (m_whitecursor - m_blackcursor) / 2.0;
double mid = (double)m_blackcursor + delta;
double tmp = (x - mid) / delta;
m_gamma = 1.0 / pow (10, tmp);
break;
}
repaint(false);
}
void KGradientSlider::mouseReleaseEvent ( TQMouseEvent * e )
{
if (e->button() != Qt::LeftButton)
return;
m_dragging = false;
repaint(false);
switch (m_grab_cursor) {
case BlackCursor:
emit modifiedBlack(m_blackcursor);
break;
case WhiteCursor:
emit modifiedWhite(m_whitecursor);
break;
case GammaCursor:
emit modifiedGamma(m_gamma);
break;
}
}
void KGradientSlider::mouseMoveEvent ( TQMouseEvent * e )
{
unsigned int x = abs(e->pos().x());
if (m_dragging == true) // Else, drag the selected point
{
if (x <= m_leftmost)
x = m_leftmost;
if(x >= m_rightmost)
x = m_rightmost;
/*if(x > 255)
x = 255;
if(x < 0)
x = 0;*/
switch (m_grab_cursor) {
case BlackCursor:
if (m_blackcursor != x)
{
m_blackcursor = x;
if (m_gammaEnabled) {
double delta = (double) (m_whitecursor - m_blackcursor) / 2.0;
double mid = (double)m_blackcursor + delta;
double tmp = log10 (1.0 / m_gamma);
m_gammacursor = (unsigned int)tqRound(mid + delta * tmp);
}
}
break;
case WhiteCursor:
if (m_whitecursor != x)
{
m_whitecursor = x;
if (m_gammaEnabled) {
double delta = (double) (m_whitecursor - m_blackcursor) / 2.0;
double mid = (double)m_blackcursor + delta;
double tmp = log10 (1.0 / m_gamma);
m_gammacursor = (unsigned int)tqRound(mid + delta * tmp);
}
}
break;
case GammaCursor:
if (m_gammacursor != x)
{
m_gammacursor = x;
double delta = (double) (m_whitecursor - m_blackcursor) / 2.0;
double mid = (double)m_blackcursor + delta;
double tmp = (x - mid) / delta;
m_gamma = 1.0 / pow (10, tmp);
}
break;
}
}
repaint(false);
}
void KGradientSlider::leaveEvent( TQEvent * )
{
}
void KGradientSlider::enableGamma(bool b)
{
m_gammaEnabled = b;
repaint(false);
}
double KGradientSlider::getGamma(void)
{
return m_gamma;
}
void KGradientSlider::modifyBlack(int v) {
if (v >= 0 && v <= (int)m_whitecursor) {
m_blackcursor = (unsigned int)v;
if (m_gammaEnabled) {
double delta = (double) (m_whitecursor - m_blackcursor) / 2.0;
double mid = (double)m_blackcursor + delta;
double tmp = log10 (1.0 / m_gamma);
m_gammacursor = (unsigned int)tqRound(mid + delta * tmp);
}
repaint(false);
}
}
void KGradientSlider::modifyWhite(int v) {
if (v >= (int)m_blackcursor && v <= 255) {
m_whitecursor = (unsigned int)v;
if (m_gammaEnabled) {
double delta = (double) (m_whitecursor - m_blackcursor) / 2.0;
double mid = (double)m_blackcursor + delta;
double tmp = log10 (1.0 / m_gamma);
m_gammacursor = (unsigned int)tqRound(mid + delta * tmp);
}
repaint(false);
}
}
void KGradientSlider::modifyGamma(double v) {
m_gamma = v;
double delta = (double) (m_whitecursor - m_blackcursor) / 2.0;
double mid = (double)m_blackcursor + delta;
double tmp = log10 (1.0 / m_gamma);
m_gammacursor = (unsigned int)tqRound(mid + delta * tmp);
repaint(false);
}
#include "kgradientslider.moc"