1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File: QtxRubberBand.cxx
21 // Author: Alexander A. BORODIN
23 #include "QtxRubberBand.h"
27 #include <QPaintEvent>
31 #include <QVectorIterator>
34 \class QtxAbstractRubberBand
35 \brief Analog of class QRubberBand with possibility of creation non-rectangular contour for selection.
37 Currently this class does not support Style functionality in full.
42 \param theParent parent widget
45 QtxAbstractRubberBand::QtxAbstractRubberBand( QWidget* theParent)
46 : QWidget( theParent/*,Qt::ToolTip*/ ),
50 setAttribute(Qt::WA_TransparentForMouseEvents);
52 setAttribute(Qt::WA_NoSystemBackground);
54 setAttribute(Qt::WA_WState_ExplicitShowHide);
56 theParent->installEventFilter(this);
57 setGeometry( QRect(QPoint(0,0), theParent->size() ) );
63 QtxAbstractRubberBand::~QtxAbstractRubberBand()
67 void QtxAbstractRubberBand::clearGeometry()
72 bool QtxAbstractRubberBand::isClosed()
77 void QtxAbstractRubberBand::paintEvent( QPaintEvent* theEvent )
79 if ( !myPoints.empty() )
81 QPixmap tiledPixmap(16, 16);
83 QPainter pixmapPainter(&tiledPixmap);
84 pixmapPainter.setPen(Qt::NoPen);
85 pixmapPainter.setBrush(QBrush( Qt::black, Qt::Dense4Pattern ));
86 pixmapPainter.setBackground(QBrush( Qt::white ));
87 pixmapPainter.setBackgroundMode(Qt::OpaqueMode);
88 pixmapPainter.drawRect(0, 0, tiledPixmap.width(), tiledPixmap.height());
90 // ### workaround for borked XRENDER
91 tiledPixmap = QPixmap::fromImage(tiledPixmap.toImage());
95 QPainter aPainter( this );
96 aPainter.setRenderHint( QPainter::Antialiasing );
97 QRect r = myPoints.boundingRect();
98 aPainter.setClipRegion( r.normalized().adjusted( -1, -1, 2, 2 ) );
99 aPainter.drawTiledPixmap( 0, 0, width(), height(), tiledPixmap);
108 QPixmap anImage( size() );
110 QImage anImage( size(), QImage::Format_ARGB32_Premultiplied );
113 anImage.fill( Qt::transparent );
114 QPainter aImgPainter( &anImage );
115 aImgPainter.setRenderHint( QPainter::Antialiasing );
116 aImgPainter.setCompositionMode(QPainter::CompositionMode_Source);
118 QPen aPen( Qt::black );
120 aImgPainter.setPen( aPen );
122 aImgPainter.drawPolyline( myPoints );
123 if ( myIsClosed && myPoints.last() != myPoints.first() )
124 aImgPainter.drawLine( myPoints.last(), myPoints.first() );
126 //aImgPainter.setPen(Qt::NoPen);
127 //aImgPainter.setBrush(QBrush( Qt::white, Qt::Dense4Pattern));
128 //aImgPainter.setCompositionMode(QPainter::CompositionMode_SourceAtop);
129 //aImgPainter.drawRect(0, 0, width(), height());
132 QPainter aPainter( this );
133 aPainter.drawPolyline( myPoints );
134 if ( myIsClosed && myPoints.last() != myPoints.first() )
135 aPainter.drawLine( myPoints.last(), myPoints.first() );
138 aPainter.drawPixmap( 0, 0, anImage );
140 aPainter.drawImage( 0, 0, anImage );
147 void QtxAbstractRubberBand::showEvent( QShowEvent* theEvent )
153 void QtxAbstractRubberBand::moveEvent( QMoveEvent* )
157 void QtxAbstractRubberBand::resizeEvent( QResizeEvent* )
161 bool QtxAbstractRubberBand::eventFilter( QObject* obj, QEvent* e )
163 if ( obj && obj == parent() && e->type() == QEvent::Resize )
165 QWidget* p = (QWidget*)parent();
166 setGeometry( QRect(QPoint(0,0), p->size() ) );
168 return QWidget::eventFilter( obj, e );
171 QRegion createRegion( const QPointF& p1, const QPointF& p2 )
176 QLineF n = QLineF( p1, p2 ).normalVector();//.unitVector();
178 n.translate( p1 * -1 );
179 QPointF nPoint = n.p2();
182 p << p1 + nPoint << p2 + nPoint << p2 - nPoint << p1 - nPoint << p1 + nPoint;
184 return QRegion( p.toPolygon() );
187 void QtxAbstractRubberBand::updateMask()
191 QVectorIterator<QPoint> it(myPoints);
192 while( it.hasNext() )
194 QPoint p = it.next();
198 QPoint np = it.peekNext();
200 if ( p == np ) continue;
202 r += createRegion( p, np );
206 r += createRegion( myPoints.last(), myPoints.first() );
213 QtxRectRubberBand::QtxRectRubberBand(QWidget* parent)
214 :QtxAbstractRubberBand( parent )
216 myPoints.resize( 4 );
220 QtxRectRubberBand::~QtxRectRubberBand()
224 void QtxRectRubberBand::initGeometry( const QRect& theRect )
227 myPoints << theRect.topLeft() << theRect.topRight() << theRect.bottomRight() << theRect.bottomLeft();
228 //setMask( QRegion( myPoints ) );
232 void QtxRectRubberBand::setStartPoint( const QPoint& thePoint )
234 myPoints[0] = thePoint;
235 myPoints[1].setY( thePoint.y() );
236 myPoints[3].setX( thePoint.x() );
240 void QtxRectRubberBand::setEndPoint( const QPoint& thePoint)
242 myPoints[2] = thePoint;
243 myPoints[1].setX( thePoint.x() );
244 myPoints[3].setY( thePoint.y() );
248 void QtxRectRubberBand::clearGeometry()
250 QMutableVectorIterator<QPoint> i(myPoints);
254 i.setValue( QPoint( -1, -1 ) );
259 QtxPolyRubberBand::QtxPolyRubberBand(QWidget* parent)
260 :QtxAbstractRubberBand( parent )
264 QtxPolyRubberBand::~QtxPolyRubberBand()
268 void QtxPolyRubberBand::initGeometry( const QPolygon& thePoints )
270 myPoints = thePoints;
274 void QtxPolyRubberBand::initGeometry( const QPoint& thePoint )
277 myPoints << thePoint;
281 void QtxPolyRubberBand::addNode( const QPoint& thePoint )
283 myPoints << thePoint;
287 void QtxPolyRubberBand::replaceLastNode( const QPoint& thePoint )
289 if ( !myPoints.empty() )
292 myPoints << thePoint;
297 void QtxPolyRubberBand::removeLastNode()
299 if ( !myPoints.empty() )
306 void QtxPolyRubberBand::setClosed( bool theFlag )
308 if (myIsClosed != theFlag )
310 myIsClosed = theFlag;