00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifdef QT_OPENGL_SUPPORT
00040 #include <QGLWidget>
00041 #endif
00042
00043 #include "hoverpoints.h"
00044
00048 HoverPoints::HoverPoints(QWidget *widget, PointShape shape)
00049 : QObject(widget)
00050 {
00051 printf("creating HoverPoints\n");
00052
00053 m_widget = widget;
00054 widget->installEventFilter(this);
00055
00056
00057 m_connectionType = LineConnection;
00058 m_sortType = NoSort;
00059 m_shape = shape;
00060 m_pointPen = QPen(QColor(255, 255, 255, 191), 1);
00061 m_connectionPen = QPen(QColor(255, 255, 255, 127), 2);
00062 m_pointBrush = QBrush(QColor(191, 191, 191, 127));
00063 m_pointSize = QSize(30, 30);
00064
00065 m_currentIndex = -1;
00066 m_editable = true;
00067 m_enabled = true;
00068
00069
00070 connect(this, SIGNAL(pointsChanged(const QPolygonF &)), m_widget, SLOT(update()));
00071 }
00072
00073
00074 void HoverPoints::setEnabled(bool enabled)
00075 {
00076 if (m_enabled != enabled) {
00077 m_enabled = enabled;
00078 m_widget->update();
00079 }
00080 }
00081
00085 bool HoverPoints::eventFilter(QObject *object, QEvent *event)
00086 {
00087 if (object == m_widget && m_enabled) {
00088 switch (event->type()) {
00089
00090 case QEvent::MouseButtonPress:
00091 {
00092 QMouseEvent *me = (QMouseEvent *) event;
00093
00094 QPointF clickPos = me->pos();
00095 int index = -1;
00096 for (int i=0; i<m_points.size(); ++i) {
00097 QPainterPath path;
00098 if (m_shape == CircleShape)
00099 path.addEllipse(pointBoundingRect(i));
00100 else
00101 path.addRect(pointBoundingRect(i));
00102
00103 if (path.contains(clickPos)) {
00104 index = i;
00105 break;
00106 }
00107 }
00108
00109 if (me->button() == Qt::LeftButton) {
00110 if (index == -1) {
00111 if (!m_editable)
00112 return false;
00113 int pos = 0;
00114
00115 if (m_sortType == XSort) {
00116 for (int i=0; i<m_points.size(); ++i)
00117 if (m_points.at(i).x() > clickPos.x()) {
00118 pos = i;
00119 break;
00120 }
00121 } else if (m_sortType == YSort) {
00122 for (int i=0; i<m_points.size(); ++i)
00123 if (m_points.at(i).y() > clickPos.y()) {
00124 pos = i;
00125 break;
00126 }
00127 }
00128
00129 m_points.insert(pos, clickPos);
00130 m_locks.insert(pos, 0);
00131 m_currentIndex = pos;
00132 firePointChange();
00133 } else {
00134 m_currentIndex = index;
00135 }
00136 return true;
00137
00138 } else if (me->button() == Qt::RightButton) {
00139 if (index >= 0 && m_editable) {
00140 if (m_locks[index] == 0) {
00141 m_locks.remove(index);
00142 m_points.remove(index);
00143 }
00144 firePointChange();
00145 return true;
00146 }
00147 }
00148
00149 }
00150 break;
00151
00152 case QEvent::MouseButtonRelease:
00153 m_currentIndex = -1;
00154 break;
00155
00156 case QEvent::MouseMove:
00157 if (m_currentIndex >= 0)
00158 movePoint(m_currentIndex, ((QMouseEvent *)event)->pos());
00159 break;
00160
00161 case QEvent::Resize:
00162 {
00163 QResizeEvent *e = (QResizeEvent *) event;
00164 if (e->oldSize().width() == 0 || e->oldSize().height() == 0)
00165 break;
00166 double stretch_x = e->size().width() / double(e->oldSize().width());
00167 double stretch_y = e->size().height() / double(e->oldSize().height());
00168 for (int i=0; i<m_points.size(); ++i) {
00169 QPointF p = m_points[i];
00170 movePoint(i, QPointF(p.x() * stretch_x, p.y() * stretch_y), false);
00171 }
00172
00173 firePointChange();
00174 break;
00175 }
00176
00177 case QEvent::Paint:
00178 {
00179 QWidget *that_widget = m_widget;
00180 m_widget = 0;
00181 QApplication::sendEvent(object, event);
00182 m_widget = that_widget;
00183 paintPoints();
00184 #ifdef QT_OPENGL_SUPPORT
00185 ArthurFrame *af = qobject_cast<ArthurFrame *>(that_widget);
00186 if (af && af->usesOpenGL())
00187 af->glWidget()->swapBuffers();
00188 #endif
00189 return true;
00190 }
00191 default:
00192 break;
00193 }
00194 }
00195
00196 return false;
00197 }
00198
00199
00200 void HoverPoints::paintPoints()
00201 {
00202 QPainter p;
00203 #ifdef QT_OPENGL_SUPPORT
00204 ArthurFrame *af = qobject_cast<ArthurFrame *>(m_widget);
00205 if (af && af->usesOpenGL())
00206 p.begin(af->glWidget());
00207 else
00208 p.begin(m_widget);
00209 #else
00210 p.begin(m_widget);
00211 #endif
00212
00213 p.setRenderHint(QPainter::Antialiasing);
00214
00215 if (m_connectionPen.style() != Qt::NoPen && m_connectionType != NoConnection) {
00216 p.setPen(m_connectionPen);
00217
00218 if (m_connectionType == CurveConnection) {
00219 QPainterPath path;
00220 path.moveTo(m_points.at(0));
00221 for (int i=1; i<m_points.size(); ++i) {
00222 QPointF p1 = m_points.at(i-1);
00223 QPointF p2 = m_points.at(i);
00224 double distance = p2.x() - p1.x();
00225
00226 path.cubicTo(p1.x() + distance / 2, p1.y(),
00227 p1.x() + distance / 2, p2.y(),
00228 p2.x(), p2.y());
00229 }
00230 p.drawPath(path);
00231 } else {
00232 p.drawPolyline(m_points);
00233 }
00234 }
00235
00236 p.setPen(m_pointPen);
00237 p.setBrush(m_pointBrush);
00238
00239 for (int i=0; i<m_points.size(); ++i) {
00240 QRectF bounds = pointBoundingRect(i);
00241 if (m_shape == CircleShape)
00242 p.drawEllipse(bounds);
00243 else
00244 p.drawRect(bounds);
00245 }
00246 }
00247
00248 static QPointF bound_point(const QPointF &point, const QRectF &bounds, int lock)
00249 {
00250 QPointF p = point;
00251
00252 double left = bounds.left();
00253 double right = bounds.right();
00254 double top = bounds.top();
00255 double bottom = bounds.bottom();
00256
00257 if (p.x() < left || (lock & HoverPoints::LockToLeft)) p.setX(left);
00258 else if (p.x() > right || (lock & HoverPoints::LockToRight)) p.setX(right);
00259
00260 if (p.y() < top || (lock & HoverPoints::LockToTop)) p.setY(top);
00261 else if (p.y() > bottom || (lock & HoverPoints::LockToBottom)) p.setY(bottom);
00262
00263 return p;
00264 }
00265
00266 void HoverPoints::setPoints(const QPolygonF &points)
00267 {
00268 m_points.clear();
00269 for (int i=0; i<points.size(); ++i)
00270 m_points << bound_point(points.at(i), boundingRect(), 0);
00271
00272 m_locks.clear();
00273 if (m_points.size() > 0) {
00274 m_locks.resize(m_points.size());
00275
00276 m_locks.fill(0);
00277 }
00278 }
00279
00280
00281 void HoverPoints::movePoint(int index, const QPointF &point, bool emitUpdate)
00282 {
00283 m_points[index] = bound_point(point, boundingRect(), m_locks.at(index));
00284 if (emitUpdate)
00285 firePointChange();
00286 }
00287
00288
00289 inline static bool x_less_than(const QPointF &p1, const QPointF &p2)
00290 {
00291 return p1.x() < p2.x();
00292 }
00293
00294
00295 inline static bool y_less_than(const QPointF &p1, const QPointF &p2)
00296 {
00297 return p1.y() < p2.y();
00298 }
00299
00303 void HoverPoints::firePointChange()
00304 {
00305
00306
00307 if (m_sortType != NoSort) {
00308
00309 QPointF oldCurrent;
00310 if (m_currentIndex != -1) {
00311 oldCurrent = m_points[m_currentIndex];
00312 }
00313
00314 if (m_sortType == XSort)
00315 qSort(m_points.begin(), m_points.end(), x_less_than);
00316 else if (m_sortType == YSort)
00317 qSort(m_points.begin(), m_points.end(), y_less_than);
00318
00319
00320 if (m_currentIndex != -1) {
00321 for (int i=0; i<m_points.size(); ++i) {
00322 if (m_points[i] == oldCurrent) {
00323 m_currentIndex = i;
00324 break;
00325 }
00326 }
00327 }
00328
00329
00330
00331 }
00332
00333
00334
00335
00336
00337
00338 emit pointsChanged(m_points);
00339 }