Salome HOME
Mouse interaction with Viewer is added
[modules/shaper.git] / src / XGUI / XGUI_RubberBand.cpp
1 #include "XGUI_RubberBand.h"
2
3 #include <QBitmap>
4 #include <QImage>
5 #include <QPaintEvent>
6 #include <QPainter>
7 #include <QPalette>
8 #include <QShowEvent>
9 #include <QVectorIterator>
10
11 /*!
12   \class QtxAbstractRubberBand
13   \brief Analog of class QRubberBand with possibility of creation non-rectangular contour for selection.
14   
15   Currently this class does not support Style functionality in full.
16 */
17
18 /*!
19   \brief Constructor
20   \param theParent parent widget
21  */
22
23 XGUI_AbstractRubberBand::XGUI_AbstractRubberBand( QWidget* theParent)
24   : QWidget( theParent ),
25     myPoints(),
26     myIsClosed( false )
27 {
28     setAttribute(Qt::WA_TransparentForMouseEvents);
29 #ifndef WIN32
30     setAttribute(Qt::WA_NoSystemBackground);
31 #endif //WIN32
32     setAttribute(Qt::WA_WState_ExplicitShowHide);
33     setVisible(false);
34     theParent->installEventFilter(this);
35     setGeometry( QRect(QPoint(0,0), theParent->size() ) );
36 }
37
38 /*!
39   \brief Destructor
40  */
41 XGUI_AbstractRubberBand::~XGUI_AbstractRubberBand()
42 {
43 }
44
45 void XGUI_AbstractRubberBand::clearGeometry()
46 {
47     myPoints.clear();
48 }
49
50 bool XGUI_AbstractRubberBand::isClosed()
51 {
52     return myIsClosed;
53 }
54
55 void XGUI_AbstractRubberBand::paintEvent( QPaintEvent* theEvent )
56 {
57     if ( !myPoints.empty() )  {
58         QPixmap tiledPixmap(16, 16);
59      
60         QPainter pixmapPainter(&tiledPixmap);
61         pixmapPainter.setPen(Qt::NoPen);
62         pixmapPainter.setBrush(QBrush( Qt::black, Qt::Dense4Pattern ));
63         pixmapPainter.setBackground(QBrush( Qt::white ));
64         pixmapPainter.setBackgroundMode(Qt::OpaqueMode);
65         pixmapPainter.drawRect(0, 0, tiledPixmap.width(), tiledPixmap.height());
66         pixmapPainter.end();
67         // ### workaround for borked XRENDER
68         tiledPixmap = QPixmap::fromImage(tiledPixmap.toImage());
69
70         QPainter aPainter( this );
71         aPainter.setRenderHint( QPainter::Antialiasing );
72         QRect r = myPoints.boundingRect();
73         aPainter.setClipRegion( r.normalized().adjusted( -1, -1, 2, 2 ) );
74         aPainter.drawTiledPixmap( 0, 0, width(), height(), tiledPixmap);
75
76         aPainter.end();
77     }
78 }
79
80 void XGUI_AbstractRubberBand::showEvent( QShowEvent* theEvent )
81 {
82     raise();
83     theEvent->ignore();
84 }
85
86 void XGUI_AbstractRubberBand::moveEvent( QMoveEvent* )
87 {
88 }
89
90 void XGUI_AbstractRubberBand::resizeEvent( QResizeEvent* )
91 {
92 }
93
94 bool XGUI_AbstractRubberBand::eventFilter( QObject* obj, QEvent* e )
95 {
96     if ( obj && obj == parent() && e->type() == QEvent::Resize ) {
97         QWidget* p = (QWidget*)parent();
98         setGeometry( QRect(QPoint(0,0), p->size() ) );
99     }
100     return QWidget::eventFilter( obj, e );
101 }
102
103 QRegion createRegion( const QPointF& p1, const QPointF& p2 )
104 {
105     if ( p1 == p2 )
106         return QRegion();
107
108     QLineF n = QLineF( p1, p2 ).normalVector();//.unitVector();
109     n.setLength( 1 );
110     n.translate( p1 * -1 );
111     QPointF nPoint = n.p2();
112
113     QPolygonF p;
114     p << p1 + nPoint << p2 + nPoint << p2 - nPoint << p1 - nPoint << p1 + nPoint;
115
116     return QRegion( p.toPolygon() );
117 }
118
119 void XGUI_AbstractRubberBand::updateMask()
120 {
121     QRegion r;
122
123     QVectorIterator<QPoint> it(myPoints);
124     while( it.hasNext() ) {
125         QPoint p = it.next();
126         if( !it.hasNext() )
127             break;
128
129         QPoint np = it.peekNext();
130       
131         if ( p == np ) continue;
132
133         r += createRegion( p, np );
134     }
135
136     if ( isClosed() )
137         r += createRegion( myPoints.last(), myPoints.first() );
138
139     setMask( r );
140 }
141
142
143 //**********************************************************
144 XGUI_RectRubberBand::XGUI_RectRubberBand(QWidget* parent)
145   :XGUI_AbstractRubberBand( parent )      
146 {
147     myPoints.resize( 4 );
148     myIsClosed = true;
149 }
150
151 XGUI_RectRubberBand::~XGUI_RectRubberBand()
152 {
153 }
154
155 void XGUI_RectRubberBand::initGeometry( const QRect& theRect )
156 {
157     myPoints.clear();
158     myPoints << theRect.topLeft() << theRect.topRight() << theRect.bottomRight() << theRect.bottomLeft();
159     //setMask( QRegion( myPoints ) );
160     updateMask();
161 }
162
163 void XGUI_RectRubberBand::setStartPoint( const QPoint& thePoint )
164 {
165     myPoints[0] = thePoint;
166     myPoints[1].setY( thePoint.y() );
167     myPoints[3].setX( thePoint.x() );
168     updateMask();
169 }
170
171 void XGUI_RectRubberBand::setEndPoint( const QPoint& thePoint)
172 {
173     myPoints[2] = thePoint;       
174     myPoints[1].setX( thePoint.x() );
175     myPoints[3].setY( thePoint.y() );
176     updateMask();
177 }
178
179 void XGUI_RectRubberBand::clearGeometry()
180 {
181     QMutableVectorIterator<QPoint> i(myPoints);
182     while (i.hasNext()) {
183         i.next();
184         i.setValue( QPoint( -1, -1 ) );
185     }
186 }
187
188 //**********************************************************
189 XGUI_PolyRubberBand::XGUI_PolyRubberBand(QWidget* parent)
190   :XGUI_AbstractRubberBand( parent )
191 {
192 }
193
194 XGUI_PolyRubberBand::~XGUI_PolyRubberBand()
195 {
196 }
197
198 void XGUI_PolyRubberBand::initGeometry( const QPolygon& thePoints )
199 {
200     myPoints = thePoints;
201     updateMask();
202 }
203
204 void XGUI_PolyRubberBand::initGeometry( const QPoint& thePoint )
205 {
206     myPoints.clear();  
207     myPoints << thePoint;
208     updateMask();
209 }
210
211 void XGUI_PolyRubberBand::addNode( const QPoint& thePoint )
212 {
213     myPoints << thePoint;
214     updateMask();
215 }
216
217 void XGUI_PolyRubberBand::replaceLastNode( const QPoint& thePoint )
218 {
219     if ( !myPoints.empty() )  {
220         myPoints.pop_back();
221         myPoints << thePoint;
222         updateMask();
223     }
224 }
225
226 void XGUI_PolyRubberBand::removeLastNode()
227 {
228     if ( !myPoints.empty() ) {
229         myPoints.pop_back();
230         updateMask();
231     }
232 }
233
234 void XGUI_PolyRubberBand::setClosed( bool theFlag )
235 {
236     if (myIsClosed != theFlag ) {
237         myIsClosed = theFlag;
238         updateMask();
239     }
240 }