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