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