Commit 677e1956 authored by Tobias Neeb's avatar Tobias Neeb
Browse files

[ADD #736] implement a class for a triangle widget used in the transferFunction2D-module

parent da1c07c2
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut 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 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include <QMenu>
#include <QKeyEvent>
#include "QGraphicsSceneContextMenuEvent"
#include "QApplication"
#include "QBrush"
#include "QPainter"
#include "QColorDialog"
#include "QGraphicsScene"
#include "QPolygonF"
#include "WTransferFunction2DTriangle.h"
#include "WTransferFunction2DTriangleWidget.h"
#include "core/common/WLogger.h"
WTransferFunction2DTriangleWidget::WTransferFunction2DTriangleWidget( WTransferFunction2DGUIWidget *parent,
WTransferFunction2DTriangle triangle,
QColor color )
{
setFlag( ItemIsMovable );
setFlag( ItemSendsScenePositionChanges );
setFlag( ItemIsSelectable );
setFlag( ItemIsFocusable );
setZValue( 3 );
// Note: this is the local coordinate system of the box widget, not of the scene
m_triangle = triangle;
m_parent = parent;
m_color = color;
m_resizePoints = NONE;
// We always start with top right and go clock wise
m_controlPoints.push_back( new WTransferFunction2DControlPoint( this, m_triangle.left(), LEFT_TRI ) );
m_controlPoints.push_back( new WTransferFunction2DControlPoint( this, m_triangle.mid(), MID_TRI ) );
m_controlPoints.push_back( new WTransferFunction2DControlPoint( this, m_triangle.right(), RIGHT_TRI ) );
connect( m_controlPoints[0], SIGNAL( resizeHandleChanged( ResizePoints, QPointF ) ),
this, SLOT( setResizeHandle( ResizePoints, QPointF ) ) );
connect( m_controlPoints[1], SIGNAL( resizeHandleChanged( ResizePoints, QPointF ) ),
this, SLOT( setResizeHandle( ResizePoints, QPointF ) ) );
connect( m_controlPoints[2], SIGNAL( resizeHandleChanged( ResizePoints, QPointF ) ),
this, SLOT( setResizeHandle( ResizePoints, QPointF ) ) );
}
WTransferFunction2DTriangleWidget::~WTransferFunction2DTriangleWidget()
{
}
QRectF WTransferFunction2DTriangleWidget::boundingRect() const
{
return m_triangle.getTriangle().boundingRect();
}
void WTransferFunction2DTriangleWidget::setControlPointsToCorner()
{
prepareGeometryChange();
m_controlPoints[0]->setPos( m_triangle.left() ); // top right
m_controlPoints[1]->setPos( m_triangle.mid() ); // bottom right
m_controlPoints[2]->setPos( m_triangle.right() ); // bottom left
// We also need to update the m_width and m_height property of the box
//m_width = (m_box.right() - m_box.left());
//m_height = (m_box.bottom() - m_box.top());
update();
}
QVariant WTransferFunction2DTriangleWidget::itemChange( GraphicsItemChange change, const QVariant &value )
{
if( change == ItemPositionChange && scene() )
{
// value is the new position.
QPointF newPos = value.toPointF();
QRectF rect = scene()->sceneRect();
// We create a bounding reactangle with the size of the parent bounds.
// Because this Rect is always moved when moving the widget,
// we have to translate it back into (0,0) of the parent bounds
// by using the inverse of the origin of this widget
rect.translate( -m_triangle.left() );
rect.setRight( rect.right() - ( m_triangle.getTriangle().boundingRect().width() ) - 1 );
rect.setBottom( rect.bottom() - ( m_triangle.getTriangle().boundingRect().height() ) - 1 );
if( !rect.contains( newPos ) )
{
// Keep the item inside the scene
newPos.setX( qMin( rect.right(), qMax( newPos.x(), rect.left() ) ) );
newPos.setY( qMin( rect.bottom(), qMax( newPos.y(), rect.top() ) ) );
return newPos;
}
//TODO(T. Neeb): Add keeping in bounds for triangle/other widgets
}
return QGraphicsItem::itemChange( change, value );
}
void WTransferFunction2DTriangleWidget::setColor( QColor color )
{
m_color = color;
this->update();
m_parent->dataChanged();
}
void WTransferFunction2DTriangleWidget::paint( QPainter *painter, const QStyleOptionGraphicsItem *, QWidget * )
{
QBrush brush( m_color );
painter->setBrush( brush );
painter->drawPolygon( m_triangle.getTriangle(), Qt::OddEvenFill );
}
void WTransferFunction2DTriangleWidget::setResizeHandle( ResizePoints handle, QPointF position )
{
m_resizePoints = handle;
prepareGeometryChange();
switch( m_resizePoints )
{
case LEFT_TRI:
m_triangle.setLeft( position );
setControlPointsToCorner();
break;
case MID_TRI:
m_triangle.setMid( position );
setControlPointsToCorner();
break;
case RIGHT_TRI:
m_triangle.setRight( position );
setControlPointsToCorner();
break;
default:
break;
}
update();
m_parent->dataChanged();
}
void WTransferFunction2DTriangleWidget::mousePressEvent( QGraphicsSceneMouseEvent *event )
{
update();
m_parent->dataChanged();
QGraphicsItem::mousePressEvent( event );
}
void WTransferFunction2DTriangleWidget::mouseMoveEvent( QGraphicsSceneMouseEvent *event )
{
update();
m_parent->dataChanged();
QGraphicsItem::mouseMoveEvent( event );
}
void WTransferFunction2DTriangleWidget::mouseReleaseEvent( QGraphicsSceneMouseEvent *event )
{
update();
m_parent->dataChanged();
QGraphicsItem::mouseReleaseEvent( event );
}
void WTransferFunction2DTriangleWidget::mouseDoubleClickEvent( QGraphicsSceneMouseEvent *event )
{
event->accept();
QGraphicsObject::mouseDoubleClickEvent( event );
update();
showColorPicker();
}
void WTransferFunction2DTriangleWidget::colorSelected( const QColor &newcolor )
{
m_color = newcolor;
if( m_parent )
{
m_parent->dataChanged();
}
}
void WTransferFunction2DTriangleWidget::showColorPicker()
{
// Create a color dialog to create an RGBA quadrupel
QColorDialog *dialog = new QColorDialog();
dialog->setCurrentColor( m_color );
dialog->setOption( QColorDialog::NoButtons );
dialog->setOption( QColorDialog::ShowAlphaChannel );
connect( dialog, SIGNAL( currentColorChanged( const QColor & ) ), this, SLOT( colorSelected( const QColor & ) ) );
dialog->open();
}
void WTransferFunction2DTriangleWidget::keyPressEvent( QKeyEvent *event )
{
if( event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete )
{
m_parent->removeTriangleWidget( this );
}
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut 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 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WTRANSFERFUNCTION2DTRIANGLEWIDGET_H
#define WTRANSFERFUNCTION2DTRIANGLEWIDGET_H
#include <vector>
#include "QGraphicsItem"
#include "WTransferFunction2DGUIWidget.h"
#include "WTransferFunction2DControlPoint.h"
#include "WTransferFunction2DEnums.h"
#include "WTransferFunction2DTriangle.h"
class WTransferFunction2DGUIWidget;
/**
* This class defines a resizable triangle and is used as a
* manipulation widget for the 2D Transfer Function.
* With this widget you select how the data is depicted
* later, through setting a color and opacity.
*
*/
class WTransferFunction2DTriangleWidget : public QGraphicsObject
{
Q_OBJECT
public:
/**
* Constructor
*
* \param parent of the triangle
* \param triangle of the widget
* \param color of the triangle
*/
explicit WTransferFunction2DTriangleWidget( WTransferFunction2DGUIWidget *parent, WTransferFunction2DTriangle triangle, QColor color );
/**
* Destructor
*/
~WTransferFunction2DTriangleWidget();
/**
* Defines the bounding rectangle of this item and returns it
*
* @return
*/
QRectF boundingRect() const override;
/**
* Method for painting which must be overriden by this subclass
*
* \param painter
* \param option
* \param widget
*/
void paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr ) override;
/**
* Get the color of the triangle.
*
* \return the color of the triangle
*/
QColor getColor()
{
return m_color;
}
/**
* Get the Triangle object
*
* @return WTransferFunction2DTriangle
*/
WTransferFunction2DTriangle getTriangle()
{
return m_triangle;
}
/**
* Set the color of the box.
*
* \param color the new color
*/
void setColor( QColor color );
public slots:
/**
* Called by the color dialog every time the user changes the color.
*
* \param color the new color
*/
void colorSelected( const QColor& color );
/**
* Sets the resize handle to a new position
*
* \param handle handle location e.g. TOPLEFT
* \param position position where it was moved to
*/
void setResizeHandle( ResizePoints handle, QPointF position );
protected:
/**
* Fires event, when mouse button is pressed
*
* @param event
*/
void mousePressEvent( QGraphicsSceneMouseEvent *event ) override;
/**
* Fires event, when mouse button is moved
*
* @param event
*/
void mouseMoveEvent( QGraphicsSceneMouseEvent *event ) override;
/**
* Fires event, when mouse button is released
*
* @param event
*/
void mouseReleaseEvent( QGraphicsSceneMouseEvent *event ) override;
/**
* Fires event, when mouse button is double clicked
*
* @param event
*/
void mouseDoubleClickEvent( QGraphicsSceneMouseEvent *event ) override;
/**
* Fires event, when a key is pressed
*
* @param event
*/
void keyPressEvent( QKeyEvent *event ) override;
/**
* Handles events, when state of this item changes
*
* from QtDocs:
* @param change is the parameter of the item that is changing
* @param value is the new value
*
* @return a Qt datatype
*/
QVariant itemChange( GraphicsItemChange change, const QVariant &value ) override;
private:
/**
* Show the color picker dialog.
**/
void showColorPicker();
/**
* Sets all control points in their desired corner of the rect
* */
void setControlPointsToCorner();
ResizePoints m_resizePoints; /*!< Flag of current selected resize point */
WTransferFunction2DGUIWidget* m_parent; /*!< The parent object */
QColor m_color; /*!< The color of the box */
std::vector< WTransferFunction2DControlPoint* > m_controlPoints; /*!< The different control handles in the corners */
WTransferFunction2DTriangle m_triangle; /*!< The triangle which is painted */
};
#endif // WTRANSFERFUNCTION2DTRIANGLEWIDGET_H
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment