Salome HOME
Restore editing of dimensions by dragging
[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   if (!r.isEmpty())\r
141     setMask(r);\r
142 }\r
143 \r
144 //**********************************************************\r
145 XGUI_RectRubberBand::XGUI_RectRubberBand(QWidget* parent)\r
146     : XGUI_AbstractRubberBand(parent)\r
147 {\r
148   myPoints.resize(4);\r
149   myIsClosed = true;\r
150 }\r
151 \r
152 XGUI_RectRubberBand::~XGUI_RectRubberBand()\r
153 {\r
154 }\r
155 \r
156 void XGUI_RectRubberBand::initGeometry(const QRect& theRect)\r
157 {\r
158   myPoints.clear();\r
159   myPoints << theRect.topLeft() << theRect.topRight() << theRect.bottomRight()\r
160            << theRect.bottomLeft();\r
161   //setMask( QRegion( myPoints ) );\r
162   updateMask();\r
163 }\r
164 \r
165 void XGUI_RectRubberBand::setStartPoint(const QPoint& thePoint)\r
166 {\r
167   myPoints[0] = thePoint;\r
168   myPoints[1].setY(thePoint.y());\r
169   myPoints[3].setX(thePoint.x());\r
170   updateMask();\r
171 }\r
172 \r
173 void XGUI_RectRubberBand::setEndPoint(const QPoint& thePoint)\r
174 {\r
175   myPoints[2] = thePoint;\r
176   myPoints[1].setX(thePoint.x());\r
177   myPoints[3].setY(thePoint.y());\r
178   updateMask();\r
179 }\r
180 \r
181 void XGUI_RectRubberBand::clearGeometry()\r
182 {\r
183   QMutableVectorIterator<QPoint> i(myPoints);\r
184   while (i.hasNext()) {\r
185     i.next();\r
186     i.setValue(QPoint(-1, -1));\r
187   }\r
188 }\r
189 \r
190 //**********************************************************\r
191 XGUI_PolyRubberBand::XGUI_PolyRubberBand(QWidget* parent)\r
192     : XGUI_AbstractRubberBand(parent)\r
193 {\r
194 }\r
195 \r
196 XGUI_PolyRubberBand::~XGUI_PolyRubberBand()\r
197 {\r
198 }\r
199 \r
200 void XGUI_PolyRubberBand::initGeometry(const QPolygon& thePoints)\r
201 {\r
202   myPoints = thePoints;\r
203   updateMask();\r
204 }\r
205 \r
206 void XGUI_PolyRubberBand::initGeometry(const QPoint& thePoint)\r
207 {\r
208   myPoints.clear();\r
209   myPoints << thePoint;\r
210   updateMask();\r
211 }\r
212 \r
213 void XGUI_PolyRubberBand::addNode(const QPoint& thePoint)\r
214 {\r
215   myPoints << thePoint;\r
216   updateMask();\r
217 }\r
218 \r
219 void XGUI_PolyRubberBand::replaceLastNode(const QPoint& thePoint)\r
220 {\r
221   if (!myPoints.empty()) {\r
222     myPoints.pop_back();\r
223     myPoints << thePoint;\r
224     updateMask();\r
225   }\r
226 }\r
227 \r
228 void XGUI_PolyRubberBand::removeLastNode()\r
229 {\r
230   if (!myPoints.empty()) {\r
231     myPoints.pop_back();\r
232     updateMask();\r
233   }\r
234 }\r
235 \r
236 void XGUI_PolyRubberBand::setClosed(bool theFlag)\r
237 {\r
238   if (myIsClosed != theFlag) {\r
239     myIsClosed = theFlag;\r
240     updateMask();\r
241   }\r
242 }\r