src/HoverPoints.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 2005-2007 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the demonstration applications of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://trolltech.com/products/qt/licenses/licensing/opensource/
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
00017 ** or contact the sales department at sales@trolltech.com.
00018 **
00019 ** In addition, as a special exception, Trolltech gives you certain
00020 ** additional rights. These rights are described in the Trolltech GPL
00021 ** Exception version 1.0, which can be found at
00022 ** http://www.trolltech.com/products/qt/gplexception/ and in the file
00023 ** GPL_EXCEPTION.txt in this package.
00024 **
00025 ** In addition, as a special exception, Trolltech, as the sole copyright
00026 ** holder for Qt Designer, grants users of the Qt/Eclipse Integration
00027 ** plug-in the right for the Qt/Eclipse Integration to link to
00028 ** functionality provided by Qt Designer and its related libraries.
00029 **
00030 ** Trolltech reserves all rights not expressly granted herein.
00031 ** 
00032 ** Trolltech ASA (c) 2007
00033 **
00034 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00035 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
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     //m_connectionType = CurveConnection;
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     //m_pointSize = QSize(11, 11);
00065     m_currentIndex = -1;
00066     m_editable = true;
00067     m_enabled = true;
00068 
00069     // update widget onDraw
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                     // Insert sort for x or y
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 //    printf("HoverPoints::firePointChange(), current=%d\n", m_currentIndex);
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         // Compensate for changed order...
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 //         printf(" - firePointChange(), current=%d\n", m_currentIndex);
00330 
00331     }
00332 
00333 //     for (int i=0; i<m_points.size(); ++i) {
00334 //         printf(" - point(%2d)=[%.2f, %.2f], lock=%d\n",
00335 //                i, m_points.at(i).x(), m_points.at(i).y(), m_locks.at(i));
00336 //     }
00337 
00338     emit pointsChanged(m_points);
00339 }

Generated on Mon Dec 10 18:18:11 2007 for VisLU by  doxygen 1.5.4