OpenWalnut  1.5.0dev
WTransferFunctionColorPoint.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <iostream>
26 
27 #include "QtCore/QMimeData"
28 #include "QColorDialog"
29 #include "QGraphicsSceneMouseEvent"
30 #include "QPainter"
31 #include "QStyleOption"
32 
33 #include "WTransferFunctionWidget.h"
34 
35 #include "WTransferFunctionColorPoint.h"
36 
37 
39  : BaseClass(),
40  radius( 8.0 ), left( 0x0 ), right( 0x0 ),
41  _parent( parent ),
42  color( QColor( 0, 0, 1, 255 ) )
43 {
44  this->setFlag( ItemIsMovable );
45  // position is always on y axis
46  this->setPos( this->pos().x(), 0 );
47 
48  //this->setFlag( QGraphicsItem::ItemIsSelectable ); //< do we want selections?
49  this->setFlag( QGraphicsItem::ItemIsMovable );
50  this->setFlag( QGraphicsItem::ItemSendsGeometryChanges );
51  this->setAcceptDrops( true );
52 
53  //this->setCursor( Qt::SplitHCursor );
54 
55  setZValue( 3 );
56 }
57 
59 {
60 }
61 
63 {
64  left = point;
65 }
66 
68 {
69  return left;
70 }
71 
73 {
74  right = point;
75 }
76 
78 {
79  return right;
80 }
81 
83 {
84  const double padding( 2 );
85  const double diameter( radius * 2 );
86  return QRectF( -radius - padding, -radius - padding, diameter + padding, radius + padding );
87 }
88 
89 void WTransferFunctionColorPoint::paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget* )
90 {
91  QRadialGradient gradient( 0.0, 0.0, radius );
92 
93  if( option->state & QStyle::State_Selected )
94  {
95  gradient.setColorAt( 0, Qt::yellow );
96  gradient.setColorAt( 1, Qt::red );
97  painter->setPen( QPen( Qt::black, 2 ) );
98  }
99  else if( option->state & QStyle::State_Sunken )
100  {
101  gradient.setColorAt( 0, color ); //QColor( Qt::yellow ).light( 120 ) );
102  gradient.setColorAt( 1, color ); //QColor( Qt::darkYellow ).light( 120 ) );
103  painter->setPen( QPen( Qt::black, 2 ) );
104  }
105  else
106  {
107  gradient.setColorAt( 0, color ); //Qt::yellow );
108  gradient.setColorAt( 1, color ); //Qt::darkYellow );
109  painter->setPen( QPen( Qt::black, 0 ) );
110  }
111 
112  QColor color = painter->pen().color();
113  color.setAlpha( 255 * 0.3 );
114  painter->setPen( QPen( color, painter->pen().width() ) );
115  painter->setBrush( gradient );
116 
117  QPolygon triangle;
118  triangle.clear();
119  triangle << QPoint( -radius, -radius );
120  triangle << QPoint( 0, 0 );
121  triangle << QPoint( radius, -radius );
122 
123  painter->drawPolygon( triangle );
124 
125  if( left && right )
126  {
127  if( option->state & QStyle::State_Sunken )
128  {
129  painter->setPen( QPen( Qt::red, 1, Qt::DashLine, Qt::RoundCap, Qt::RoundJoin ) );
130  }
131  else
132  {
133  painter->setPen( QPen( Qt::black, 1, Qt::DashLine, Qt::RoundCap, Qt::RoundJoin ) );
134  }
135  // FIXME: fixed size in code
136  painter->drawLine( QPoint( 0, 0 ), QPoint( 0, scene()->sceneRect().height() ) );
137  }
138 }
139 
140 QVariant WTransferFunctionColorPoint::itemChange( GraphicsItemChange change, const QVariant &value )
141 {
142  // if( change == ItemPositionChange )
143  // {
144  // QPointF newPos = value.toPointF();
145  //
146  // QRectF boundingBox( this->scene()->sceneRect() );
147  // if( boundingBox.left() > newPos.x() || boundingBox.right() < newPos.x() )
148  // {
149  // newPos.setX( qMin( boundingBox.right(), qMax( newPos.x(), boundingBox.left() ) ) );
150  // if ( newPos.y() != 0 )
151  // newPos.setY( 0 );
152  // return newPos;
153  // }
154  // if ( newPos.y() != 0 )
155  // {
156  // newPos.setY( 0 );
157  //
158  // return newPos;
159  // }
160  // }
161 
162  // // This is the wrong place for such an update :-(
163  // if ( _parent )
164  // {
165  // _parent->forceRedraw();
166  // }
167 
168  if( change == ItemPositionChange )
169  {
170  QPointF newPos = value.toPointF();
171  this->setToolTip( QString( "isovalue=" ) + QString::number( newPos.x() ) + " color=("
172  + QString::number( color.red() ) +','
173  + QString::number( color.green() ) +','
174  + QString::number( color.blue() ) + ')' );
175  if( _parent )
176  _parent->dataChanged();
177  }
178 
179  return BaseClass::itemChange( change, value );
180 }
181 
182 void WTransferFunctionColorPoint::mouseDoubleClickEvent( QGraphicsSceneMouseEvent *event )
183 {
184  BaseClass::mouseDoubleClickEvent( event );
185 
186  showColorPicker();
187 }
188 
189 void WTransferFunctionColorPoint::colorSelected( const QColor &newcolor )
190 {
191  color = newcolor;
192  color.setAlpha( 255 ); //< force opacity
193  //this->update();
194  if( _parent )
195  {
196  _parent->dataChanged();
197  }
198 }
199 
200 void WTransferFunctionColorPoint::mouseMoveEvent( QGraphicsSceneMouseEvent *event )
201 {
202  if( left && right )
203  {
204  //this->update();
205  BaseClass::mouseMoveEvent( event );
206 
207 
208 #if 1
209  QRectF boundingBox( this->scene()->sceneRect() );
210 
211  if( !left )
212  {
213  this->setPos( 0, this->pos().y() );
214  }
215 
216  if( !right )
217  {
218  this->setPos( boundingBox.x() + boundingBox.width(), this->pos().y() );
219  }
220 #endif
221 
222  this->clampToRectangle( boundingBox );
223  this->clampToLeftAndRight();
224 
225  // color markers are always at zero
226  this->setPos( this->pos().x(), 0 );
227  }
228 }
229 
230 void WTransferFunctionColorPoint::mousePressEvent( QGraphicsSceneMouseEvent *event )
231 {
232  //this->update();
233  BaseClass::mousePressEvent( event );
234  _parent->setCurrentColor( this );
235 }
236 
237 void WTransferFunctionColorPoint::mouseReleaseEvent( QGraphicsSceneMouseEvent *event )
238 {
239  //this->update();
240  BaseClass::mouseReleaseEvent( event );
241 }
242 
244 {
245  if( left )
246  {
247  if( this->pos().x() <= left->pos().x() )
248  {
249  this->setPos( left->pos().x() + 1, this->pos().y() );
250  }
251  }
252  if( right )
253  {
254  if( this->pos().x() >= right->pos().x() )
255  {
256  this->setPos( right->pos().x() - 1, this->pos().y() );
257  }
258  }
259 }
260 
261 void WTransferFunctionColorPoint::clampToRectangle( const QRectF& rectangle )
262 {
263  qreal x( this->pos().x() );
264  qreal y( this->pos().y() );
265 
266  const qreal xMin( rectangle.x() );
267  const qreal xMax( xMin + rectangle.width() );
268  const qreal yMin( rectangle.y() );
269  const qreal yMax( yMin + rectangle.height() );
270 
271  x = qMax( x, xMin );
272  x = qMin( x, xMax );
273 
274  y = qMax( y, yMin );
275  y = qMin( y, yMax );
276 
277  this->setPos( x, y );
278 }
279 
281 {
282  return color;
283 }
284 
285 void WTransferFunctionColorPoint::dragEnterEvent( QGraphicsSceneDragDropEvent* event )
286 {
287  if( event->mimeData()->hasColor() )
288  {
289  event->setAccepted( true );
290  }
291 }
292 
293 void WTransferFunctionColorPoint::dropEvent( QGraphicsSceneDragDropEvent* event )
294 {
295  if( event->mimeData()->hasColor() )
296  {
297  color = qvariant_cast<QColor>( event->mimeData()->colorData() );
298  color.setAlpha( 255 ); //< force opacity
299  //this->update();
300  if( _parent )
301  _parent->dataChanged();
302  }
303 }
304 
305 void WTransferFunctionColorPoint::contextMenuEvent( QGraphicsSceneContextMenuEvent* event )
306 {
307  // I get right clicks as context menu events on OSX which may be intended,
308  // but I get both at the same time, so I create a new object and get its
309  // context menu as well, which is confusing. Therefore, this is disabled
310  // right now.
311  // Additionally, I do not know how to remove the item from its own menu
312 #ifdef ALLOW_CONTEXT_MENU
313  event->accept();
314  QMenu menu;
315  QAction *removeAction = menu.addAction( "Remove" );
316  QAction *changeColor = menu.addAction( "Change Color" );
317  QAction *selectedAction = menu.exec( event->screenPos() );
318 
319  if( selectedAction == removeAction )
320  {
321  }
322  if( selectedAction == changeColor )
323  {
324  showColorPicker();
325  }
326 #endif
327  BaseClass::contextMenuEvent( event );
328 }
329 
331 {
332  QColorDialog *dialog = new QColorDialog( );
333  dialog->setCurrentColor( color );
334  dialog->setOption( QColorDialog::NoButtons );
335  connect( dialog, SIGNAL( currentColorChanged( const QColor& ) ), this, SLOT( colorSelected( const QColor& ) ) );
336  //dialog->open( this, SLOT( colorSelected( const QColor& ) ) );
337  dialog->open();
338 }
339 
A control point for the color function.
void colorSelected(const QColor &color)
Called by the color dialog every time the user changes the color.
WTransferFunctionWidget * _parent
the parent widget
void mousePressEvent(QGraphicsSceneMouseEvent *event)
Handles press move events.
virtual void dropEvent(QGraphicsSceneDragDropEvent *event)
Drop implementation for items that contain a color.
void clampToLeftAndRight()
Helper for item changed.
QVariant itemChange(GraphicsItemChange change, const QVariant &value)
Handles change notifications.
void setLeft(WTransferFunctionColorPoint *left)
Set the item left of us.
virtual ~WTransferFunctionColorPoint()
Default destructor.
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
Handler for context menu envents.
void showColorPicker()
Show the color picker dialog.
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=0x0)
Paint the handle and additional item hints.
WTransferFunctionColorPoint * right
the entry to the right of our entry
void clampToRectangle(const QRectF &rectangle)
Helper for item changed.
WTransferFunctionColorPoint * getRight() const
Returns the item right of this item.
double radius
the radius used for paining of the handle
void setRight(WTransferFunctionColorPoint *right)
Set the item right of us.
virtual void dragEnterEvent(QGraphicsSceneDragDropEvent *event)
Drag enter implementation for items that contain a color.
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
Handles mouse double click events by opening a color selector if the item is clicked.
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
Handles mouse move events.
WTransferFunctionColorPoint * getLeft() const
Returns the item left of the this item.
QRectF boundingRect() const
The bounding rectangle used for paint and click events.
WTransferFunctionColorPoint * left
the entry left of this entry
WTransferFunctionColorPoint(WTransferFunctionWidget *parent=0x0)
Default constructor.
void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
Handles mouse move events.
A widget that holds a scene to display and modify the transfer function.
void setCurrentColor(WTransferFunctionColorPoint *ccurrent)
Similar to setCurrent but for Color control points.
void dataChanged()
Notification that the data changed, i.e., a control point has been moved or a color changed.