![]() |
RTXI 1.3
|
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 }