00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <qlabel.h>
00013 #include <qpainter.h>
00014 #include <qfocusdata.h>
00015 #include "qwt_plot.h"
00016 #include "qwt_plot_layout.h"
00017 #include "qwt_plot_dict.h"
00018 #include "qwt_rect.h"
00019 #include "qwt_scale.h"
00020 #include "qwt_legend.h"
00021 #include "qwt_dyngrid_layout.h"
00022 #include "qwt_plot_canvas.h"
00023 #include "qwt_math.h"
00024 #include "qwt_paint_buffer.h"
00025
00032 QwtPlot::QwtPlot(QWidget *parent, const char *name) :
00033 QFrame(parent, name, WRepaintNoErase|WResizeNoErase)
00034 {
00035 initPlot();
00036 }
00037
00038
00045 QwtPlot::QwtPlot(const QString &title, QWidget *parent, const char *name) :
00046 QFrame(parent, name, WRepaintNoErase|WResizeNoErase)
00047 {
00048 initPlot(title);
00049 }
00050
00052 QwtPlot::~QwtPlot()
00053 {
00054 delete d_layout;
00055 delete d_curves;
00056 delete d_markers;
00057 delete d_grid;
00058 }
00059
00064 void QwtPlot::initPlot(const QString &title)
00065 {
00066 d_layout = new QwtPlotLayout;
00067
00068 d_curves = new QwtCurveDict;
00069 d_markers = new QwtMarkerDict;
00070
00071 d_autoReplot = FALSE;
00072
00073 d_lblTitle = new QLabel(title, this);
00074 d_lblTitle->setFont(QFont("Helvetica", 14,QFont::Bold));
00075 d_lblTitle->setAlignment(AlignHCenter|AlignBottom|WordBreak|ExpandTabs);
00076
00077 d_legend = new QwtLegend(this);
00078 d_autoLegend = FALSE;
00079
00080 d_scale[yLeft] = new QwtScale(QwtScale::Left, this, "yLeft");
00081 d_scale[yRight] = new QwtScale(QwtScale::Right, this, "yRight");
00082 d_scale[xTop] = new QwtScale(QwtScale::Top, this, "xTop");
00083 d_scale[xBottom] = new QwtScale(QwtScale::Bottom, this, "xBottom");
00084
00085 initAxes();
00086
00087 d_grid = new QwtPlotGrid(this);
00088 d_grid->setPen(QPen(black, 0, DotLine));
00089 d_grid->setXDiv(d_sdiv[xBottom]);
00090 d_grid->setYDiv(d_sdiv[yLeft]);
00091 d_grid->enableXMin(FALSE);
00092 d_grid->enableYMin(FALSE);
00093 d_grid->setAxis(xBottom, yLeft);
00094
00095 d_canvas = new QwtPlotCanvas(this);
00096 d_canvas->setFrameStyle(QFrame::Panel|QFrame::Sunken);
00097 d_canvas->setLineWidth(2);
00098 d_canvas->setMidLineWidth(0);
00099
00100 connect(d_canvas, SIGNAL(mousePressed(const QMouseEvent &)),
00101 this, SIGNAL(plotMousePressed(const QMouseEvent &)));
00102 connect(d_canvas, SIGNAL(mouseMoved(const QMouseEvent &)),
00103 this, SIGNAL(plotMouseMoved(const QMouseEvent &)));
00104 connect(d_canvas, SIGNAL(mouseReleased(const QMouseEvent &)),
00105 this, SIGNAL(plotMouseReleased(const QMouseEvent &)));
00106
00107 updateTabOrder();
00108 }
00109
00111 void QwtPlot::initAxes()
00112 {
00113 int axis;
00114
00115 QFont fscl("Helvetica", 10);
00116 QFont fttl("Helvetica", 12, QFont::Bold);
00117
00118 for(axis = 0; axis < axisCnt; axis++)
00119 {
00120 d_scale[axis]->setFont(fscl);
00121 d_scale[axis]->setTitleFont(fttl);
00122 d_scale[axis]->setBaselineDist(2);
00123 }
00124
00125 d_axisEnabled[yLeft] = TRUE;
00126 d_axisEnabled[yRight] = FALSE;
00127 d_axisEnabled[xBottom] = TRUE;
00128 d_axisEnabled[xTop] = FALSE;
00129
00130 for (axis=0; axis < axisCnt; axis++)
00131 {
00132 d_as[axis].adjust(0.0,1000.0,TRUE);
00133 d_sdiv[axis] = d_as[axis].scaleDiv();
00134 d_scale[axis]->setScaleDiv(d_sdiv[axis]);
00135 }
00136 }
00137
00141 bool QwtPlot::event(QEvent *e)
00142 {
00143 bool ok = QFrame::event(e);
00144 switch(e->type())
00145 {
00146 #if 0
00147 case QEvent::ChildInserted:
00148 case QEvent::ChildRemoved:
00149 #endif
00150 case QEvent::LayoutHint:
00151 updateLayout();
00152 break;
00153 default:;
00154 }
00155 return ok;
00156 }
00157
00162 void QwtPlot::autoRefresh()
00163 {
00164 if (d_autoReplot)
00165 replot();
00166 }
00167
00178 void QwtPlot::enableOutline(bool tf)
00179 {
00180 d_canvas->enableOutline(tf);
00181 }
00182
00197 void QwtPlot::setAutoReplot(bool tf)
00198 {
00199 d_autoReplot = tf;
00200 }
00201
00205 bool QwtPlot::autoReplot() const
00206 {
00207 return d_autoReplot;
00208 }
00209
00214 void QwtPlot::setTitle(const QString &t)
00215 {
00216 d_lblTitle->setText(t);
00217 }
00218
00223 QString QwtPlot::title() const
00224 {
00225 return d_lblTitle->text();
00226 }
00227
00228
00233 void QwtPlot::setTitleFont(const QFont &f)
00234 {
00235 d_lblTitle->setFont(f);
00236 }
00237
00241 QFont QwtPlot::titleFont() const
00242 {
00243 return d_lblTitle->font();
00244 }
00245
00249 QwtPlotLayout *QwtPlot::plotLayout()
00250 {
00251 return d_layout;
00252 }
00253
00257 const QwtPlotLayout *QwtPlot::plotLayout() const
00258 {
00259 return d_layout;
00260 }
00261
00265 QLabel *QwtPlot::titleLabel()
00266 {
00267 return d_lblTitle;
00268 }
00269
00273 const QLabel *QwtPlot::titleLabel() const
00274 {
00275 return d_lblTitle;
00276 }
00277
00282 QwtLegend *QwtPlot::legend()
00283 {
00284 return d_legend;
00285 }
00286
00291 const QwtLegend *QwtPlot::legend() const
00292 {
00293 return d_legend;
00294 }
00295
00296
00300 QwtPlotCanvas *QwtPlot::canvas()
00301 {
00302 return d_canvas;
00303 }
00304
00308 const QwtPlotCanvas *QwtPlot::canvas() const
00309 {
00310 return d_canvas;
00311 }
00312
00314 QSizePolicy QwtPlot::sizePolicy() const
00315 {
00316 QSizePolicy sp;
00317 sp.setHorData( QSizePolicy::MinimumExpanding );
00318 sp.setVerData( QSizePolicy::MinimumExpanding );
00319 return sp;
00320 }
00321
00327 QSize QwtPlot::sizeHint() const
00328 {
00329 int dw = 0;
00330 int dh = 0;
00331 for ( int axis = 0; axis < axisCnt; axis++ )
00332 {
00333 if ( d_axisEnabled[axis] )
00334 {
00335 const int niceDist = 40;
00336 const QwtScale *scale = d_scale[axis];
00337 const int majCnt = scale->scaleDraw()->scaleDiv().majCnt();
00338
00339 if ( axis == yLeft || axis == yRight )
00340 {
00341 int hDiff = (majCnt - 1) * niceDist
00342 - scale->minimumSizeHint().height();
00343 if ( hDiff > dh )
00344 dh = hDiff;
00345 }
00346 else
00347 {
00348 int wDiff = (majCnt - 1) * niceDist
00349 - scale->minimumSizeHint().width();
00350 if ( wDiff > dw )
00351 dw = wDiff;
00352 }
00353 }
00354 }
00355 return minimumSizeHint() + QSize(dw, dh);
00356 }
00357
00361 QSize QwtPlot::minimumSizeHint() const
00362 {
00363 QSize hint = d_layout->minimumSizeHint(this);
00364 hint += QSize(2 * frameWidth(), 2 * frameWidth());
00365
00366 return hint;
00367 }
00368
00370 void QwtPlot::resizeEvent(QResizeEvent *e)
00371 {
00372 QFrame::resizeEvent(e);
00373 updateLayout();
00374 }
00375
00383 void QwtPlot::replot()
00384 {
00385 bool doAutoReplot = autoReplot();
00386 setAutoReplot(FALSE);
00387
00388 updateAxes();
00389
00390 if ( d_canvas->contentsRect().isValid() )
00391 {
00392 QwtPaintBuffer paintBuffer(d_canvas, d_canvas->contentsRect());
00393 drawCanvas(paintBuffer.painter());
00394 }
00395
00396 setAutoReplot(doAutoReplot);
00397 }
00398
00403 void QwtPlot::updateLayout()
00404 {
00405 d_layout->activate(this, contentsRect());
00406
00407
00408
00409
00410 if (!d_lblTitle->text().isEmpty())
00411 {
00412 d_lblTitle->setGeometry(d_layout->titleRect());
00413 if (!d_lblTitle->isVisible())
00414 d_lblTitle->show();
00415 }
00416 else
00417 d_lblTitle->hide();
00418
00419 for (int axis = 0; axis < axisCnt; axis++ )
00420 {
00421 if (d_axisEnabled[axis])
00422 {
00423 d_scale[axis]->setGeometry(d_layout->scaleRect(axis));
00424
00425 if ( axis == xBottom || axis == xTop )
00426 {
00427 QRegion r(d_layout->scaleRect(axis));
00428 if ( d_axisEnabled[yLeft] )
00429 r = r.subtract(QRegion(d_layout->scaleRect(yLeft)));
00430 if ( d_axisEnabled[yRight] )
00431 r = r.subtract(QRegion(d_layout->scaleRect(yRight)));
00432 r.translate(-d_layout->scaleRect(axis).x(),
00433 -d_layout->scaleRect(axis).y());
00434
00435 d_scale[axis]->setMask(r);
00436 }
00437 if (!d_scale[axis]->isVisible())
00438 d_scale[axis]->show();
00439 }
00440 else
00441 d_scale[axis]->hide();
00442 }
00443
00444 if (d_legend->itemCount() > 0)
00445 {
00446 d_legend->setGeometry(d_layout->legendRect());
00447 d_legend->show();
00448 }
00449 else
00450 d_legend->hide();
00451
00452 d_canvas->setGeometry(d_layout->canvasRect());
00453 d_canvas->update();
00454 }
00455
00457 void QwtPlot::updateAxes()
00458 {
00459 int i;
00460 bool resetDone[axisCnt];
00461 for (i = 0; i < axisCnt; i++)
00462 resetDone[i] = FALSE;
00463
00464
00465
00466
00467
00468 QwtPlotCurveIterator itc = curveIterator();
00469 for (const QwtPlotCurve *c = itc.toFirst(); c != 0; c = ++itc )
00470 {
00471 if (c->dataSize() > 0)
00472 {
00473 int axis = c->xAxis();
00474 if ( d_as[axis].autoScale() )
00475 {
00476 if ( !resetDone[axis] )
00477 {
00478 d_as[axis].reset();
00479 resetDone[axis] = TRUE;
00480 }
00481 d_as[axis].adjust(c->minXValue(), c->maxXValue());
00482 }
00483
00484 axis = c->yAxis();
00485 if ( d_as[axis].autoScale() )
00486 {
00487 if ( !resetDone[axis] )
00488 {
00489 d_as[axis].reset();
00490 resetDone[axis] = TRUE;
00491 }
00492 d_as[axis].adjust(c->minYValue(), c->maxYValue());
00493 }
00494 }
00495 }
00496
00497
00498
00499
00500 for (i=0; i<axisCnt; i++)
00501 {
00502 d_sdiv[i] = d_as[i].scaleDiv();
00503 d_scale[i]->setScaleDiv(d_sdiv[i]);
00504
00505 int startDist, endDist;
00506 d_scale[i]->minBorderDist(startDist, endDist);
00507 d_scale[i]->setBorderDist(startDist, endDist);
00508 }
00509
00510 d_grid->setXDiv(d_sdiv[d_grid->xAxis()]);
00511 d_grid->setYDiv(d_sdiv[d_grid->yAxis()]);
00512 }
00513
00515
00516 void QwtPlot::updateTabOrder()
00517 {
00518
00519
00520
00521
00522
00523
00524 if ( d_canvas->focusPolicy() == NoFocus || focusData() == NULL )
00525 return;
00526
00527
00528
00529 for ( int i = 0; i < focusData()->count(); i++ )
00530 {
00531 if ( focusData()->next() == d_canvas )
00532 break;
00533 }
00534
00535 const bool canvasFirst = d_layout->legendPos() == Qwt::Bottom ||
00536 d_layout->legendPos() == Qwt::Right;
00537
00538 for ( int j = 0; j < focusData()->count(); j++ )
00539 {
00540 QWidget *w = canvasFirst ? focusData()->next() : focusData()->prev();
00541
00542 if ( w->focusPolicy() != NoFocus
00543 && w->parent() && w->parent() == d_legend->contentsWidget() )
00544 {
00545 if ( canvasFirst )
00546 {
00547 do
00548 {
00549 w = focusData()->prev();
00550 } while ( w->focusPolicy() == NoFocus );
00551 }
00552
00553 if ( w != d_canvas )
00554 setTabOrder(w, d_canvas);
00555 break;
00556 }
00557 }
00558 }
00559
00561
00562
00563 void QwtPlot::drawContents( QPainter * )
00564 {
00565
00566
00567 QRegion cr( contentsRect() );
00568 cr = cr.subtract( childrenRegion() );
00569 erase( cr );
00570 }
00571
00582 void QwtPlot::drawCanvas(QPainter *painter)
00583 {
00584 QwtDiMap map[axisCnt];
00585 for ( int axis = 0; axis < axisCnt; axis++ )
00586 map[axis] = canvasMap(axis);
00587
00588 drawCanvasItems(painter,
00589 d_canvas->contentsRect(), map, QwtPlotPrintFilter());
00590 }
00591
00600 void QwtPlot::drawCanvasItems(QPainter *painter, const QRect &rect,
00601 const QwtDiMap map[], const QwtPlotPrintFilter &pfilter) const
00602 {
00603
00604
00605
00606 if ( pfilter.options() & QwtPlotPrintFilter::PrintGrid )
00607 {
00608 if ( d_grid->enabled() )
00609 {
00610 d_grid->draw(painter, rect,
00611 map[d_grid->xAxis()], map[d_grid->yAxis()]);
00612 }
00613 }
00614
00615
00616
00617
00618 QwtPlotCurveIterator itc = curveIterator();
00619 for (QwtPlotCurve *curve = itc.toFirst(); curve != 0; curve = ++itc )
00620 {
00621 if ( curve->enabled() )
00622 {
00623 curve->draw(painter,
00624 map[curve->xAxis()], map[curve->yAxis()]);
00625 }
00626 }
00627
00628
00629
00630
00631 QwtPlotMarkerIterator itm = markerIterator();
00632 for (QwtPlotMarker *marker = itm.toFirst(); marker != 0; marker = ++itm )
00633 {
00634 if ( marker->enabled() )
00635 {
00636 marker->draw(painter,
00637 map[marker->xAxis()].transform(marker->xValue()),
00638 map[marker->yAxis()].transform(marker->yValue()),
00639 rect);
00640 }
00641 }
00642 }
00643
00656 void QwtPlot::drawCurve(long key, int from, int to)
00657 {
00658 QwtPlotCurve *curve = d_curves->find(key);
00659 if ( !curve )
00660 return;
00661
00662 QPainter p(canvas());
00663
00664 p.setClipping(TRUE);
00665 p.setClipRect(canvas()->rect());
00666
00667 curve->draw(&p,
00668 canvasMap(curve->xAxis()), canvasMap(curve->yAxis()),
00669 from, to);
00670 }
00671
00679 QwtDiMap QwtPlot::canvasMap(int axis) const
00680 {
00681 QwtDiMap map;
00682 if ( d_canvas && d_scale[axis] )
00683 {
00684 const QwtScale *s = d_scale[axis];
00685 map = *s->scaleDraw();
00686 if ( axis == yLeft || axis == yRight )
00687 {
00688 int y = s->y() + s->startBorderDist() - d_canvas->y();
00689 int h = s->height() - s->startBorderDist() - s->endBorderDist();
00690 map.setIntRange(y + h - 1, y);
00691 }
00692 else
00693 {
00694 int x = s->x() + s->startBorderDist() - d_canvas->x();
00695 int w = s->width() - s->startBorderDist() - s->endBorderDist();
00696 map.setIntRange(x, x + w - 1);
00697 }
00698 }
00699 return map;
00700 }
00701
00709 void QwtPlot::setMargin(int margin)
00710 {
00711 if ( margin < 0 )
00712 margin = 0;
00713
00714 if ( margin != d_layout->margin() )
00715 {
00716 d_layout->setMargin(margin);
00717 updateLayout();
00718 }
00719 }
00720
00725 int QwtPlot::margin() const
00726 {
00727 return d_layout->margin();
00728 }
00729
00738 void QwtPlot::setCanvasBackground(const QColor &c)
00739 {
00740 QPalette p = d_canvas->palette();
00741
00742 for ( int i = 0; i < QPalette::NColorGroups; i++ )
00743 p.setColor((QPalette::ColorGroup)i, QColorGroup::Background, c);
00744
00745 canvas()->setPalette(p);
00746 }
00747
00754 const QColor & QwtPlot::canvasBackground() const
00755 {
00756 return canvas()->palette().color(
00757 QPalette::Normal, QColorGroup::Background);
00758 }
00759
00766 void QwtPlot::setCanvasLineWidth(int w)
00767 {
00768 canvas()->setLineWidth(w);
00769 }
00770
00776 int QwtPlot::canvasLineWidth() const
00777 {
00778 return canvas()->lineWidth();
00779 }
00780
00811 void QwtPlot::setOutlineStyle(Qwt::Shape os)
00812 {
00813 d_canvas->setOutlineStyle(os);
00814 }
00815
00816
00817
00822 void QwtPlot::setOutlinePen(const QPen &pn)
00823 {
00824 d_canvas->setOutlinePen(pn);
00825 }
00826
00831 bool QwtPlot::axisValid(int axis)
00832 {
00833 return ((axis >= QwtPlot::yLeft) && (axis < QwtPlot::axisCnt));
00834 }
00835
00836
00840 bool QwtPlot::outlineEnabled() const
00841 {
00842 return d_canvas->outlineEnabled();
00843 }
00844
00848 const QPen & QwtPlot::outlinePen() const
00849 {
00850 return d_canvas->outlinePen();
00851 }
00852
00857 Qwt::Shape QwtPlot::outlineStyle() const
00858 {
00859 return d_canvas->outlineStyle();
00860 }
00861
00867 void QwtPlot::lgdClicked()
00868 {
00869 if ( sender()->isWidgetType() )
00870 {
00871 long key = d_legend->key((QWidget *)sender());
00872 if ( key >= 0 )
00873 emit legendClicked(key);
00874 }
00875 }
00876
00878 void QwtPlot::clear()
00879 {
00880 d_legend->clear();
00881 d_curves->clear();
00882 d_markers->clear();
00883 }
00884
00885
00887 void QwtPlot::removeCurves()
00888 {
00889 d_curves->clear();
00890 d_legend->clear();
00891 autoRefresh();
00892 }
00893
00895 void QwtPlot::removeMarkers()
00896 {
00897 d_markers->clear();
00898 autoRefresh();
00899 }
00900
00911 void QwtPlot::setAutoLegend(bool tf)
00912 {
00913 d_autoLegend = tf;
00914 }
00915
00919 bool QwtPlot::autoLegend() const
00920 {
00921 return d_autoLegend;
00922 }
00923
00924
00934 void QwtPlot::enableLegend(bool enable, long curveKey)
00935 {
00936 bool isUpdateEnabled = d_legend->isUpdatesEnabled();
00937 d_legend->setUpdatesEnabled(FALSE);
00938
00939 if ( curveKey < 0 )
00940 {
00941 if ( enable )
00942 {
00943 if ( d_legend->itemCount() < d_curves->count() )
00944 {
00945
00946
00947 d_legend->clear();
00948
00949 QwtPlotCurveIterator itc = curveIterator();
00950 for ( const QwtPlotCurve *curve = itc.toFirst();
00951 curve != 0; curve = ++itc )
00952 {
00953 insertLegendItem(itc.currentKey());
00954 }
00955 }
00956 }
00957 else
00958 {
00959 d_legend->clear();
00960 }
00961 }
00962 else
00963 {
00964 QWidget *legendItem = d_legend->findItem(curveKey);
00965 if ( enable )
00966 {
00967 if ( d_curves->find(curveKey) && !legendItem )
00968 insertLegendItem(curveKey);
00969 }
00970 else
00971 delete legendItem;
00972 }
00973
00974 d_legend->setUpdatesEnabled(isUpdateEnabled);
00975 updateLayout();
00976 }
00977
00983 bool QwtPlot::legendEnabled(long curveKey) const
00984 {
00985 return d_legend->findItem(curveKey) != 0;
00986 }
00987
01006 void QwtPlot::setLegendPos(int pos, double ratio)
01007 {
01008 if (pos != d_layout->legendPos())
01009 {
01010 d_layout->setLegendPos(pos, ratio);
01011
01012 QLayout *l = d_legend->contentsWidget()->layout();
01013 if ( l && l->inherits("QwtDynGridLayout") )
01014 {
01015 QwtDynGridLayout *tl = (QwtDynGridLayout *)l;
01016 if ( d_layout->legendPos() == Qwt::Top ||
01017 d_layout->legendPos() == Qwt::Bottom )
01018 {
01019 tl->setMaxCols(0);
01020 }
01021 else
01022 tl->setMaxCols(1);
01023 }
01024
01025 updateLayout();
01026 updateTabOrder();
01027 }
01028 }
01029
01034 int QwtPlot::legendPos() const
01035 {
01036 return d_layout->legendPos();
01037 }
01038
01043 void QwtPlot::setLegendFont(const QFont &f)
01044 {
01045 d_legend->setFont(f);
01046 if (d_legend->isVisible())
01047 updateLayout();
01048 }
01049
01054 void QwtPlot::setLegendFrameStyle(int st)
01055 {
01056 d_legend->setFrameStyle(st);
01057 updateLayout();
01058 }
01059
01063 int QwtPlot::legendFrameStyle() const
01064 {
01065 return d_legend->frameStyle();
01066 }
01067
01071 const QFont QwtPlot::legendFont() const
01072 {
01073 return d_legend->font();
01074 }
01075
01082 void QwtPlot::setLegendDisplayPolicy(int policy, int mode)
01083 {
01084 d_legend->setDisplayPolicy(policy, mode);
01085
01086 for (QwtPlotCurveIterator iter=curveIterator(); iter.current(); ++iter)
01087 updateLegendItem(iter.currentKey());
01088 }