2020-03-05 17:04:31 +01:00

267 lines
10 KiB
C++

/****************************************************************************
* MeshLab o o *
* A versatile mesh processing toolbox o o *
* _ O _ *
* Copyright(C) 2005 \/)\/ *
* Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved. *
* *
* 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 (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
/****************************************************************************
History
Revision 1.0 2008/02/20 Alessandro Maione, Federico Bellucci
FIRST RELEASE
****************************************************************************/
#include "eqhandle.h"
#include <QMouseEvent>
#include <QGraphicsSceneMouseEvent>
#include <math.h>
EqHandle::EqHandle(CHART_INFO *environment_info, QColor color, QPointF position,
EQUALIZER_HANDLE_TYPE type, EqHandle** handles, qreal* midHandlePercentilePosition, QDoubleSpinBox* spinbox,
int zOrder, int size):
Handle (environment_info, color, position, zOrder, size)
{
setSize(size);
_type = type;
_barHeight = environment_info->chartHeight();
_handlesPointer = handles;
_midHandlePercentilePosition = midHandlePercentilePosition;
_spinBoxPointer = spinbox;
// Setting triangle position above EqHandle
_triangle[0] = QPointF(-_size/2,-_size);
_triangle[1] = QPointF(_size/2, -_size);
_triangle[2] = QPointF(0, -1.87f*_size);
}
EqHandle::~EqHandle(void)
{
}
void EqHandle::paint ( QPainter * painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/ )
{
painter->setPen(_color);
painter->setBrush(_color);
painter->drawLine(0, -_size, 0, -_barHeight); // painting the vertical bar
painter->drawPolygon ( _triangle, 3); // painting the triangle above EqHandle
painter->drawRect(-_size/2, -_size, _size, _size); // painting the base rect of EqHandle
}
QRectF EqHandle::boundingRect () const
{
return QRectF(-_size/2, -_barHeight, _size, _barHeight);
}
/* Overload method implementing the movement of EqHandle
Note: Left [Right] handle can also move "outside" the histogram causing a stretching of it.
Moving the handle again "inside" the histogram reset gradually its original size
(the histogram is recalculated for every MouseMoveEvent call "outside" of it).
The process of stretching is managed by QualityMapperDialog.
The handle just notify its position relative to he histogram.
*/
void EqHandle::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
setCursor(Qt::OpenHandCursor);
QPointF newPos = event->scenePos();
qreal handleOffset = fabs(newPos.x()-pos().x());
if (handleOffset >= std::numeric_limits<float>::epsilon())
{
switch (_type)
{
case MID_HANDLE:
// Mid handle can move only between left and right handle
if ( (newPos.x() > _handlesPointer[LEFT_HANDLE]->pos().x()) && (newPos.x() < _handlesPointer[RIGHT_HANDLE]->pos().x()) )
{
*_midHandlePercentilePosition = calculateMidHandlePercentilePosition(newPos.x());
moveMidHandle();
}
emit positionChanged(); // for gammaCorrectionLabel
break;
case LEFT_HANDLE:
{
// calculating new spinbox value associated to handle
qreal newQualityValue = positionToQuality(newPos.x());
if (newQualityValue < _spinBoxPointer->minimum())
break;
// Left handle can move only on the left of right handle
if (newPos.x() < _handlesPointer[RIGHT_HANDLE]->pos().x())
{
// Changing minimum/maximum value of others spinboxes
_handlesPointer[RIGHT_HANDLE]->_spinBoxPointer->setMinimum(newQualityValue);
_handlesPointer[MID_HANDLE]->_spinBoxPointer->setMinimum(newQualityValue);
// Emitting new quality value of the handle to spinbox
_spinBoxPointer->blockSignals(true);
emit positionChangedToSpinBox((double)newQualityValue);
_spinBoxPointer->blockSignals(false);
// if left handle is "inside" histogram
if ( newQualityValue >= _chartInfo->minX )
{
emit insideHistogram(this,true); // for redrawing equalizerHistogram bars, if needed
setPos(newPos.x(), pos().y());
}
else
emit insideHistogram(this,false);
emit positionChanged(); // for redrawing transferFunctionScene and moving midHandle
}
}
break;
case RIGHT_HANDLE:
{
// calculating new spinbox value associated to handle
qreal newQualityValue = positionToQuality(newPos.x());
if (newQualityValue > _spinBoxPointer->maximum()) // Why this control??? It seems to be never reached!
break;
// Right handle can move only on the right of left handle
if (newPos.x() > _handlesPointer[LEFT_HANDLE]->pos().x())
{
// Changing minimum/maximum value of others spinboxes
_handlesPointer[LEFT_HANDLE]->_spinBoxPointer->setMaximum(newQualityValue);
_handlesPointer[MID_HANDLE]->_spinBoxPointer->setMaximum(newQualityValue);
// Emitting new quality value of the handle to spinbox
_spinBoxPointer->blockSignals(true);
emit positionChangedToSpinBox((double)newQualityValue);
_spinBoxPointer->blockSignals(false);
// if right handle is "inside" histogram
if ( newQualityValue <= _chartInfo->maxX )
{
emit insideHistogram(this,true); // for redrawing equalizerHistogram bars, if needed
setPos(newPos.x(), pos().y());
}
else
emit insideHistogram(this,false);
emit positionChanged(); // for redrawing transferFunctionScene and moving midHandle
}
}
break;
case NUMBER_OF_EQHANDLES:
break;
}
}
}
/*
Method for moving midHandle and setting its associated spinbox
*/
void EqHandle::moveMidHandle()
{
assert(_type==MID_HANDLE);
// Calculating new absolute position of the mid handle depending on its relative pos to the other handles
qreal newPosX = _handlesPointer[LEFT_HANDLE]->pos().x() + *_midHandlePercentilePosition * (_handlesPointer[RIGHT_HANDLE]->pos().x() - _handlesPointer[LEFT_HANDLE]->pos().x());
setPos(newPosX, pos().y());
qreal newSpinboxValue = positionToQuality(newPosX);
// Emitting new quality value of the handle to spinbox
_spinBoxPointer->blockSignals(true);
emit positionChangedToSpinBox((double)newSpinboxValue);
_spinBoxPointer->blockSignals(false);
//emit positionChanged(); // for gammaCorrectionLabel
}
/*
Method invoked by spinbox value changing. Updates the position of the associated handle.
*/
void EqHandle::setXBySpinBoxValueChanged(double spinBoxValue)
{
// Min and Max quality values are normally the values of the min e max spinboxes, but they are different if an handle is "outside" the histogram
float maxQ = (_handlesPointer[RIGHT_HANDLE]->_spinBoxPointer->value() > _chartInfo->maxX)?_handlesPointer[RIGHT_HANDLE]->_spinBoxPointer->value():_chartInfo->maxX;
float minQ = (_handlesPointer[LEFT_HANDLE]->_spinBoxPointer->value() < _chartInfo->minX)?_handlesPointer[LEFT_HANDLE]->_spinBoxPointer->value() :_chartInfo->minX;
qreal newHandleX;
switch (_type)
{
case MID_HANDLE:
newHandleX = qualityToPosition(spinBoxValue, minQ, maxQ);
if ( (newHandleX > _handlesPointer[LEFT_HANDLE]->pos().x()) && (newHandleX < _handlesPointer[RIGHT_HANDLE]->pos().x()) )
{
*_midHandlePercentilePosition = calculateMidHandlePercentilePosition(newHandleX);
moveMidHandle();
emit positionChanged(); // for redrawing transferFunctionScene and moving midHandle
}
break;
case LEFT_HANDLE:
newHandleX = qualityToPosition(spinBoxValue, _chartInfo->minX, _chartInfo->maxX);
if (newHandleX < _handlesPointer[RIGHT_HANDLE]->pos().x())
{
// Changing minimum/maximum value of others spinboxes
_handlesPointer[RIGHT_HANDLE]->_spinBoxPointer->setMinimum(spinBoxValue);
_handlesPointer[MID_HANDLE]->_spinBoxPointer->setMinimum(spinBoxValue);
// if left handle is "inside" histogram
if ( newHandleX >= _chartInfo->leftBorder() )
{
setPos(newHandleX, pos().y());
emit insideHistogram(this,true); // for redrawing equalizerHistogram bars, if needed
}
else
{
setPos(_chartInfo->leftBorder(), pos().y());
emit insideHistogram(this,false);
}
emit positionChanged(); // for redrawing transferFunctionScene and moving midHandle
}
break;
case RIGHT_HANDLE:
newHandleX = qualityToPosition(spinBoxValue, _chartInfo->minX, _chartInfo->maxX);
if (newHandleX > _handlesPointer[LEFT_HANDLE]->pos().x())
{
// Changing minimum/maximum value of other spinboxes
_handlesPointer[LEFT_HANDLE]->_spinBoxPointer->setMaximum(spinBoxValue);
_handlesPointer[MID_HANDLE]->_spinBoxPointer->setMaximum(spinBoxValue);
// if right handle is "inside" histogram
if ( newHandleX <= _chartInfo->rightBorder() )
{
setPos(newHandleX, pos().y());
emit insideHistogram(this,true); // invalidates equalizerHistogram scene
}
else
{
setPos(_chartInfo->rightBorder(), pos().y());
emit insideHistogram(this,false);
}
emit positionChanged(); // for redrawing transferFunctionScene and moving midHandle
}
break;
case NUMBER_OF_EQHANDLES:
break;
}
}