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