RTXI 1.3
plugins/include/scrollzoomer.cpp
Go to the documentation of this file.
00001 #include <qevent.h>
00002 #include <qwt-qt3/qwt_plot_canvas.h>
00003 #include <qwt-qt3/qwt_plot_layout.h>
00004 #include <qwt-qt3/qwt_scale_engine.h>
00005 #include <qwt-qt3/qwt_scale_widget.h>
00006 #include "scrollbar.h"
00007 #include "scrollzoomer.h"
00008 
00009 class ScrollData
00010 {
00011 public:
00012   ScrollData() :
00013     scrollBar(NULL), position(ScrollZoomer::OppositeToScale),
00014 #if QT_VERSION < 0x040000
00015         mode(QScrollView::Auto)
00016 #else
00017   mode(Qt::ScrollBarAsNeeded)
00018 #endif
00019   {
00020   }
00021 
00022   ~ScrollData()
00023   {
00024     delete scrollBar;
00025   }
00026 
00027   ScrollBar *scrollBar;
00028   ScrollZoomer::ScrollBarPosition position;
00029 #if QT_VERSION < 0x040000
00030   QScrollView::ScrollBarMode mode;
00031 #else
00032   Qt::ScrollBarPolicy mode;
00033 #endif
00034 };
00035 
00036 ScrollZoomer::ScrollZoomer(QwtPlotCanvas *canvas) :
00037   QwtPlotZoomer(canvas), d_cornerWidget(NULL), d_hScrollData(NULL),
00038       d_vScrollData(NULL), d_inZoom(false), d_alignCanvasToScales(false)
00039 {
00040   if (!canvas)
00041     return;
00042 
00043   d_hScrollData = new ScrollData;
00044   d_vScrollData = new ScrollData;
00045 }
00046 
00047 ScrollZoomer::~ScrollZoomer()
00048 {
00049   delete d_cornerWidget;
00050   delete d_vScrollData;
00051   delete d_hScrollData;
00052 }
00053 
00054 void
00055 ScrollZoomer::rescale()
00056 {
00057   QwtScaleWidget *xScale = plot()->axisWidget(xAxis());
00058   QwtScaleWidget *yScale = plot()->axisWidget(yAxis());
00059 
00060   if (zoomRectIndex() <= 0)
00061     {
00062       if (d_inZoom)
00063         {
00064           xScale->setMinBorderDist(0, 0);
00065           yScale->setMinBorderDist(0, 0);
00066 
00067           QwtPlotLayout *layout = plot()->plotLayout();
00068           layout->setAlignCanvasToScales(d_alignCanvasToScales);
00069 
00070           d_inZoom = false;
00071         }
00072     }
00073   else
00074     {
00075       if (!d_inZoom)
00076         {
00077           /*
00078            We set a minimum border distance.
00079            Otherwise the canvas size changes when scrolling,
00080            between situations where the major ticks are at
00081            the canvas borders (requiring extra space for the label)
00082            and situations where all labels can be painted below/top
00083            or left/right of the canvas.
00084            */
00085           int start, end;
00086 
00087           xScale->getBorderDistHint(start, end);
00088           xScale->setMinBorderDist(start, end);
00089 
00090           yScale->getBorderDistHint(start, end);
00091           yScale->setMinBorderDist(start, end);
00092 
00093           QwtPlotLayout *layout = plot()->plotLayout();
00094           d_alignCanvasToScales = layout->alignCanvasToScales();
00095           layout->setAlignCanvasToScales(false);
00096 
00097           d_inZoom = true;
00098         }
00099     }
00100 
00101   QwtPlotZoomer::rescale();
00102   updateScrollBars();
00103 }
00104 
00105 ScrollBar *
00106 ScrollZoomer::scrollBar(Qt::Orientation o)
00107 {
00108   ScrollBar *&sb = (o == Qt::Vertical) ? d_vScrollData->scrollBar
00109       : d_hScrollData->scrollBar;
00110 
00111   if (sb == NULL)
00112     {
00113       sb = new ScrollBar(o, canvas());
00114       sb->hide();
00115       connect(sb, SIGNAL(valueChanged(Qt::Orientation, double, double)),
00116           SLOT(scrollBarMoved(Qt::Orientation, double, double)));
00117     }
00118   return sb;
00119 }
00120 
00121 ScrollBar *
00122 ScrollZoomer::horizontalScrollBar() const
00123 {
00124   return d_hScrollData->scrollBar;
00125 }
00126 
00127 ScrollBar *
00128 ScrollZoomer::verticalScrollBar() const
00129 {
00130   return d_vScrollData->scrollBar;
00131 }
00132 
00133 #if QT_VERSION < 0x040000
00134 void
00135 ScrollZoomer::setHScrollBarMode(QScrollView::ScrollBarMode mode)
00136 #else
00137 void ScrollZoomer::setHScrollBarMode(Qt::ScrollBarPolicy mode)
00138 #endif
00139 {
00140   if (hScrollBarMode() != mode)
00141     {
00142       d_hScrollData->mode = mode;
00143       updateScrollBars();
00144     }
00145 }
00146 
00147 #if QT_VERSION < 0x040000
00148 void
00149 ScrollZoomer::setVScrollBarMode(QScrollView::ScrollBarMode mode)
00150 #else
00151 void ScrollZoomer::setVScrollBarMode(Qt::ScrollBarPolicy mode)
00152 #endif
00153 {
00154   if (vScrollBarMode() != mode)
00155     {
00156       d_vScrollData->mode = mode;
00157       updateScrollBars();
00158     }
00159 }
00160 
00161 #if QT_VERSION < 0x040000
00162 QScrollView::ScrollBarMode
00163 ScrollZoomer::hScrollBarMode() const
00164 #else
00165 Qt::ScrollBarPolicy ScrollZoomer::hScrollBarMode() const
00166 #endif
00167 {
00168   return d_hScrollData->mode;
00169 }
00170 
00171 #if QT_VERSION < 0x040000
00172 QScrollView::ScrollBarMode
00173 ScrollZoomer::vScrollBarMode() const
00174 #else
00175 Qt::ScrollBarPolicy ScrollZoomer::vScrollBarMode() const
00176 #endif
00177 {
00178   return d_vScrollData->mode;
00179 }
00180 
00181 void
00182 ScrollZoomer::setHScrollBarPosition(ScrollBarPosition pos)
00183 {
00184   if (d_hScrollData->position != pos)
00185     {
00186       d_hScrollData->position = pos;
00187       updateScrollBars();
00188     }
00189 }
00190 
00191 void
00192 ScrollZoomer::setVScrollBarPosition(ScrollBarPosition pos)
00193 {
00194   if (d_vScrollData->position != pos)
00195     {
00196       d_vScrollData->position = pos;
00197       updateScrollBars();
00198     }
00199 }
00200 
00201 ScrollZoomer::ScrollBarPosition
00202 ScrollZoomer::hScrollBarPosition() const
00203 {
00204   return d_hScrollData->position;
00205 }
00206 
00207 ScrollZoomer::ScrollBarPosition
00208 ScrollZoomer::vScrollBarPosition() const
00209 {
00210   return d_vScrollData->position;
00211 }
00212 
00213 void
00214 ScrollZoomer::setCornerWidget(QWidget *w)
00215 {
00216   if (w != d_cornerWidget)
00217     {
00218       if (canvas())
00219         {
00220           delete d_cornerWidget;
00221           d_cornerWidget = w;
00222           if (d_cornerWidget->parent() != canvas())
00223             {
00224 #if QT_VERSION < 0x040000
00225               d_cornerWidget->reparent(canvas(), QPoint(0, 0));
00226 #else
00227               d_cornerWidget->setParent(canvas());
00228 #endif
00229             }
00230 
00231           updateScrollBars();
00232         }
00233     }
00234 }
00235 
00236 QWidget *
00237 ScrollZoomer::cornerWidget() const
00238 {
00239   return d_cornerWidget;
00240 }
00241 
00242 bool
00243 ScrollZoomer::eventFilter(QObject *o, QEvent *e)
00244 {
00245   if (o == canvas())
00246     {
00247       switch (e->type())
00248         {
00249       case QEvent::Resize:
00250         {
00251           const int fw = ((QwtPlotCanvas *) canvas())->frameWidth();
00252 
00253           QRect rect;
00254           rect.setSize(((QResizeEvent *) e)->size());
00255           rect.setRect(rect.x() + fw, rect.y() + fw, rect.width() - 2 * fw,
00256               rect.height() - 2 * fw);
00257 
00258           layoutScrollBars(rect);
00259           break;
00260         }
00261       case QEvent::ChildRemoved:
00262         {
00263           const QObject *child = ((QChildEvent *) e)->child();
00264           if (child == d_cornerWidget)
00265             d_cornerWidget = NULL;
00266           else if (child == d_hScrollData->scrollBar)
00267             d_hScrollData->scrollBar = NULL;
00268           else if (child == d_vScrollData->scrollBar)
00269             d_vScrollData->scrollBar = NULL;
00270           break;
00271         }
00272       default:
00273         break;
00274         }
00275     }
00276   return QwtPlotZoomer::eventFilter(o, e);
00277 }
00278 
00279 bool
00280 ScrollZoomer::needScrollBar(Qt::Orientation o) const
00281 {
00282 #if QT_VERSION < 0x040000
00283   QScrollView::ScrollBarMode mode;
00284 #else
00285   Qt::ScrollBarPolicy mode;
00286 #endif
00287   double zoomMin, zoomMax, baseMin, baseMax;
00288 
00289   if (o == Qt::Horizontal)
00290     {
00291       mode = d_hScrollData->mode;
00292       baseMin = zoomBase().left();
00293       baseMax = zoomBase().right();
00294       zoomMin = zoomRect().left();
00295       zoomMax = zoomRect().right();
00296     }
00297   else
00298     {
00299       mode = d_vScrollData->mode;
00300       baseMin = zoomBase().top();
00301       baseMax = zoomBase().bottom();
00302       zoomMin = zoomRect().top();
00303       zoomMax = zoomRect().bottom();
00304     }
00305 
00306   bool needed = false;
00307   switch (mode)
00308     {
00309 #if QT_VERSION < 0x040000
00310   case QScrollView::AlwaysOn:
00311 #else
00312     case Qt::ScrollBarAlwaysOn:
00313 #endif
00314     needed = true;
00315     break;
00316 #if QT_VERSION < 0x040000
00317   case QScrollView::AlwaysOff:
00318 #else
00319     case Qt::ScrollBarAlwaysOff:
00320 #endif
00321     needed = false;
00322     break;
00323   default:
00324     {
00325       if (baseMin < zoomMin || baseMax > zoomMax)
00326         needed = true;
00327       break;
00328     }
00329     }
00330   return needed;
00331 }
00332 
00333 void
00334 ScrollZoomer::updateScrollBars()
00335 {
00336   if (!canvas())
00337     return;
00338 
00339   const int xAxis = QwtPlotZoomer::xAxis();
00340   const int yAxis = QwtPlotZoomer::yAxis();
00341 
00342   int xScrollBarAxis = xAxis;
00343   if (hScrollBarPosition() == OppositeToScale)
00344     xScrollBarAxis = oppositeAxis(xScrollBarAxis);
00345 
00346   int yScrollBarAxis = yAxis;
00347   if (vScrollBarPosition() == OppositeToScale)
00348     yScrollBarAxis = oppositeAxis(yScrollBarAxis);
00349 
00350   QwtPlotLayout *layout = plot()->plotLayout();
00351 
00352   bool showHScrollBar = needScrollBar(Qt::Horizontal);
00353   if (showHScrollBar)
00354     {
00355       ScrollBar *sb = scrollBar(Qt::Horizontal);
00356 
00357       sb->setPalette(plot()->palette());
00358 
00359       const QwtScaleDiv *sd = plot()->axisScaleDiv(xAxis);
00360       sb->setInverted(sd->lowerBound() > sd->upperBound());
00361 
00362       sb->setBase(zoomBase().left(), zoomBase().right());
00363       sb->moveSlider(zoomRect().left(), zoomRect().right());
00364 
00365       if (!sb->isVisibleTo(canvas()))
00366         {
00367           sb->show();
00368           layout->setCanvasMargin(layout->canvasMargin(xScrollBarAxis)
00369               + sb->extent(), xScrollBarAxis);
00370         }
00371     }
00372   else
00373     {
00374       if (horizontalScrollBar())
00375         {
00376           horizontalScrollBar()->hide();
00377           layout->setCanvasMargin(layout->canvasMargin(xScrollBarAxis)
00378               - horizontalScrollBar()->extent(), xScrollBarAxis);
00379         }
00380     }
00381 
00382   bool showVScrollBar = needScrollBar(Qt::Vertical);
00383   if (showVScrollBar)
00384     {
00385       ScrollBar *sb = scrollBar(Qt::Vertical);
00386 
00387       sb->setPalette(plot()->palette());
00388 
00389       const QwtScaleDiv *sd = plot()->axisScaleDiv(yAxis);
00390       sb->setInverted(sd->lowerBound() < sd->upperBound());
00391 
00392       sb->setBase(zoomBase().top(), zoomBase().bottom());
00393       sb->moveSlider(zoomRect().top(), zoomRect().bottom());
00394 
00395       if (!sb->isVisibleTo(canvas()))
00396         {
00397           sb->show();
00398           layout->setCanvasMargin(layout->canvasMargin(yScrollBarAxis)
00399               + sb->extent(), yScrollBarAxis);
00400         }
00401     }
00402   else
00403     {
00404       if (verticalScrollBar())
00405         {
00406           verticalScrollBar()->hide();
00407           layout->setCanvasMargin(layout->canvasMargin(yScrollBarAxis)
00408               - verticalScrollBar()->extent(), yScrollBarAxis);
00409         }
00410     }
00411 
00412   if (showHScrollBar && showVScrollBar)
00413     {
00414       if (d_cornerWidget == NULL)
00415         {
00416           d_cornerWidget = new QWidget(canvas());
00417 #if QT_VERSION >= 0x040100
00418           d_cornerWidget->setAutoFillBackground(true);
00419 #endif
00420           d_cornerWidget->setPalette(plot()->palette());
00421         }
00422       d_cornerWidget->show();
00423     }
00424   else
00425     {
00426       if (d_cornerWidget)
00427         d_cornerWidget->hide();
00428     }
00429 
00430   layoutScrollBars(((QwtPlotCanvas *) canvas())->contentsRect());
00431   plot()->updateLayout();
00432 }
00433 
00434 void
00435 ScrollZoomer::layoutScrollBars(const QRect &rect)
00436 {
00437   int hPos = xAxis();
00438   if (hScrollBarPosition() == OppositeToScale)
00439     hPos = oppositeAxis(hPos);
00440 
00441   int vPos = yAxis();
00442   if (vScrollBarPosition() == OppositeToScale)
00443     vPos = oppositeAxis(vPos);
00444 
00445   ScrollBar *hScrollBar = horizontalScrollBar();
00446   ScrollBar *vScrollBar = verticalScrollBar();
00447 
00448   const int hdim = hScrollBar ? hScrollBar->extent() : 0;
00449   const int vdim = vScrollBar ? vScrollBar->extent() : 0;
00450 
00451   if (hScrollBar && hScrollBar->isVisible())
00452     {
00453       int x = rect.x();
00454       int y = (hPos == QwtPlot::xTop) ? rect.top() : rect.bottom() - hdim + 1;
00455       int w = rect.width();
00456 
00457       if (vScrollBar && vScrollBar->isVisible())
00458         {
00459           if (vPos == QwtPlot::yLeft)
00460             x += vdim;
00461           w -= vdim;
00462         }
00463 
00464       hScrollBar->setGeometry(x, y, w, hdim);
00465     }
00466   if (vScrollBar && vScrollBar->isVisible())
00467     {
00468       int pos = yAxis();
00469       if (vScrollBarPosition() == OppositeToScale)
00470         pos = oppositeAxis(pos);
00471 
00472       int x = (vPos == QwtPlot::yLeft) ? rect.left() : rect.right() - vdim + 1;
00473       int y = rect.y();
00474 
00475       int h = rect.height();
00476 
00477       if (hScrollBar && hScrollBar->isVisible())
00478         {
00479           if (hPos == QwtPlot::xTop)
00480             y += hdim;
00481 
00482           h -= hdim;
00483         }
00484 
00485       vScrollBar->setGeometry(x, y, vdim, h);
00486     }
00487   if (hScrollBar && hScrollBar->isVisible() && vScrollBar
00488       && vScrollBar->isVisible())
00489     {
00490       if (d_cornerWidget)
00491         {
00492           QRect cornerRect(vScrollBar->pos().x(), hScrollBar->pos().y(), vdim,
00493               hdim);
00494           d_cornerWidget->setGeometry(cornerRect);
00495         }
00496     }
00497 }
00498 
00499 void
00500 ScrollZoomer::scrollBarMoved(Qt::Orientation o, double min, double)
00501 {
00502   if (o == Qt::Horizontal)
00503     move(min, zoomRect().top());
00504   else
00505     move(zoomRect().left(), min);
00506 
00507   emit zoomed(zoomRect());
00508 }
00509 
00510 int
00511 ScrollZoomer::oppositeAxis(int axis) const
00512 {
00513   switch (axis)
00514     {
00515   case QwtPlot::xBottom:
00516     return QwtPlot::xTop;
00517   case QwtPlot::xTop:
00518     return QwtPlot::xBottom;
00519   case QwtPlot::yLeft:
00520     return QwtPlot::yRight;
00521   case QwtPlot::yRight:
00522     return QwtPlot::yLeft;
00523   default:
00524     break;
00525     }
00526 
00527   return axis;
00528 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines