# qwt_legend_item.cpp

    00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
    00002  * Qwt Widget Library
    00003  * Copyright (C) 1997   Josef Wilgen
    00004  * Copyright (C) 2002   Uwe Rathmann
    00005  *
    00006  * This library is free software; you can redistribute it and/or
    00007  * modify it under the terms of the Qwt License, Version 1.0
    00008  *****************************************************************************/
    00009
    00010 // vim: expandtab
    00011
    00012 #include <qpainter.h>
    00013 #include <qdrawutil.h>
    00014 #include <qstyle.h>
    00015 #include <qpen.h>
    00016 #if QT_VERSION >= 0x040000
    00017 #include <qevent.h>
    00018 #include <qstyleoption.h>
    00019 #endif
    00020 #include "qwt_math.h"
    00021 #include "qwt_painter.h"
    00022 #include "qwt_symbol.h"
    00023 #include "qwt_legend_item.h"
    00024
    00025 static const int ButtonFrame = 2;
    00026 static const int Margin = 2;
    00027
    00028 static QSize buttonShift(const QwtLegendItem *w)
    00029 {
    00030 #if QT_VERSION < 0x040000
    00031     const int ph = w->style().pixelMetric(
    00032         QStyle::PM_ButtonShiftHorizontal, w);
    00033     const int pv = w->style().pixelMetric(
    00034         QStyle::PM_ButtonShiftVertical, w);
    00035 #else
    00036     QStyleOption option;
    00037     option.init(w);
    00038
    00039     const int ph = w->style()->pixelMetric(
    00040         QStyle::PM_ButtonShiftHorizontal, &option, w);
    00041     const int pv = w->style()->pixelMetric(
    00042         QStyle::PM_ButtonShiftVertical, &option, w);
    00043 #endif
    00044     return QSize(ph, pv);
    00045 }
    00046
    00047 class QwtLegendItem::PrivateData
    00048 {
    00049 public:
    00050     PrivateData():
    00051         itemMode(QwtLegend::ReadOnlyItem),
    00052         isDown(false),
    00053         identifierWidth(8),
    00054         identifierMode(QwtLegendItem::ShowLine | QwtLegendItem::ShowText),
    00055         curvePen(Qt::NoPen),
    00056         spacing(Margin)
    00057     {
    00058     }
    00059
    00060     QwtLegend::LegendItemMode itemMode;
    00061     bool isDown;
    00062
    00063     int identifierWidth;
    00064     int identifierMode;
    00065     QwtSymbol symbol;
    00066     QPen curvePen;
    00067
    00068     int spacing;
    00069 };
    00070
    00074 QwtLegendItem::QwtLegendItem(QWidget *parent):
    00075     QwtTextLabel(parent)
    00076 {
    00077     d_data = new PrivateData;
    00078     init(QwtText());
    00079 }
    00080
    00087 QwtLegendItem::QwtLegendItem(const QwtSymbol &symbol,
    00088         const QPen &curvePen, const QwtText &text,
    00089         QWidget *parent):
    00090     QwtTextLabel(parent)
    00091 {
    00092     d_data = new PrivateData;
    00093
    00094     d_data->symbol = symbol;
    00095     d_data->curvePen = curvePen;
    00096
    00097     init(text);
    00098 }
    00099
    00100 void QwtLegendItem::init(const QwtText &text)
    00101 {
    00102     setMargin(Margin);
    00103     setIndent(margin() + d_data->identifierWidth + 2 * d_data->spacing);
    00104     setText(text);
    00105 }
    00106
    00108 QwtLegendItem::~QwtLegendItem()
    00109 {
    00110     delete d_data;
    00111     d_data = NULL;
    00112 }
    00113
    00120 void QwtLegendItem::setText(const QwtText &text)
    00121 {
    00122     const int flags = Qt::AlignLeft | Qt::AlignVCenter
    00123 #if QT_VERSION < 0x040000
    00124         | Qt::WordBreak | Qt::ExpandTabs;
    00125 #else
    00126         | Qt::TextExpandTabs | Qt::TextWordWrap;
    00127 #endif
    00128
    00129     QwtText txt = text;
    00130     txt.setRenderFlags(flags);
    00131
    00132     QwtTextLabel::setText(txt);
    00133 }
    00134
    00142 void QwtLegendItem::setItemMode(QwtLegend::LegendItemMode mode)
    00143 {
    00144     d_data->itemMode = mode;
    00145     d_data->isDown = false;
    00146
    00147 #if QT_VERSION >= 0x040000
    00148     using namespace Qt;
    00149 #endif
    00150     setFocusPolicy(mode != QwtLegend::ReadOnlyItem ? TabFocus : NoFocus);
    00151     setMargin(ButtonFrame + Margin);
    00152
    00153     updateGeometry();
    00154 }
    00155
    00161 QwtLegend::LegendItemMode QwtLegendItem::itemMode() const
    00162 {
    00163     return d_data->itemMode;
    00164 }
    00165
    00173 void QwtLegendItem::setIdentifierMode(int mode)
    00174 {
    00175     if ( mode != d_data->identifierMode )
    00176     {
    00177         d_data->identifierMode = mode;
    00178         update();
    00179     }
    00180 }
    00181
    00186 int QwtLegendItem::identifierMode() const
    00187 {
    00188     return d_data->identifierMode;
    00189 }
    00190
    00199 void QwtLegendItem::setIdentfierWidth(int width)
    00200 {
    00201     width = qwtMax(width, 0);
    00202     if ( width != d_data->identifierWidth )
    00203     {
    00204         d_data->identifierWidth = width;
    00205         setIndent(margin() + d_data->identifierWidth
    00206             + 2 * d_data->spacing);
    00207     }
    00208 }
    00214 int QwtLegendItem::identifierWidth() const
    00215 {
    00216     return d_data->identifierWidth;
    00217 }
    00218
    00224 void QwtLegendItem::setSpacing(int spacing)
    00225 {
    00226     spacing = qwtMax(spacing, 0);
    00227     if ( spacing != d_data->spacing )
    00228     {
    00229         d_data->spacing = spacing;
    00230         setIndent(margin() + d_data->identifierWidth
    00231             + 2 * d_data->spacing);
    00232     }
    00233 }
    00234
    00239 int QwtLegendItem::spacing() const
    00240 {
    00241     return d_data->spacing;
    00242 }
    00243
    00250 void QwtLegendItem::setSymbol(const QwtSymbol &symbol)
    00251 {
    00252     if ( symbol != d_data->symbol )
    00253     {
    00254         d_data->symbol = symbol;
    00255         update();
    00256     }
    00257 }
    00258
    00263 const QwtSymbol& QwtLegendItem::symbol() const
    00264 {
    00265     return d_data->symbol;
    00266 }
    00267
    00268
    00275 void QwtLegendItem::setCurvePen(const QPen &pen)
    00276 {
    00277     if ( pen != d_data->curvePen )
    00278     {
    00279         d_data->curvePen = pen;
    00280         update();
    00281     }
    00282 }
    00283
    00288 const QPen& QwtLegendItem::curvePen() const
    00289 {
    00290     return d_data->curvePen;
    00291 }
    00292
    00298 void QwtLegendItem::drawIdentifier(
    00299     QPainter *painter, const QRect &rect) const
    00300 {
    00301     if ( rect.isEmpty() )
    00302         return;
    00303
    00304     if ( (d_data->identifierMode & ShowLine ) && (d_data->curvePen.style() != Qt::NoPen) )
    00305     {
    00306         painter->save();
    00307         painter->setPen(d_data->curvePen);
    00308         QwtPainter::drawLine(painter, rect.left(), rect.center().y(),
    00309             rect.right(), rect.center().y());
    00310         painter->restore();
    00311     }
    00312
    00313     if ( (d_data->identifierMode & ShowSymbol)
    00314         && (d_data->symbol.style() != QwtSymbol::NoSymbol) )
    00315     {
    00316         QSize symbolSize =
    00317             QwtPainter::metricsMap().screenToLayout(d_data->symbol.size());
    00318
    00319         // scale the symbol size down if it doesn't fit into rect.
    00320
    00321         if ( rect.width() < symbolSize.width() )
    00322         {
    00323             const double ratio =
    00324                 double(symbolSize.width()) / double(rect.width());
    00325             symbolSize.setWidth(rect.width());
    00326             symbolSize.setHeight(qRound(symbolSize.height() / ratio));
    00327         }
    00328         if ( rect.height() < symbolSize.height() )
    00329         {
    00330             const double ratio =
    00331                 double(symbolSize.width()) / double(rect.width());
    00332             symbolSize.setHeight(rect.height());
    00333             symbolSize.setWidth(qRound(symbolSize.width() / ratio));
    00334         }
    00335
    00336         QRect symbolRect;
    00337         symbolRect.setSize(symbolSize);
    00338         symbolRect.moveCenter(rect.center());
    00339
    00340         painter->save();
    00341         painter->setBrush(d_data->symbol.brush());
    00342         painter->setPen(d_data->symbol.pen());
    00343         d_data->symbol.draw(painter, symbolRect);
    00344         painter->restore();
    00345     }
    00346 }
    00347
    00354 void QwtLegendItem::drawItem(QPainter *painter, const QRect &rect) const
    00355 {
    00356     painter->save();
    00357
    00358     const QwtMetricsMap &map = QwtPainter::metricsMap();
    00359
    00360     const int m = map.screenToLayoutX(margin());
    00361     const int spacing = map.screenToLayoutX(d_data->spacing);
    00362     const int identifierWidth = map.screenToLayoutX(d_data->identifierWidth);
    00363
    00364     const QRect identifierRect(rect.x() + m, rect.y(),
    00365         identifierWidth, rect.height());
    00366     drawIdentifier(painter, identifierRect);
    00367
    00368     // Label
    00369
    00370     QRect titleRect = rect;
    00371     titleRect.setX(identifierRect.right() + 2 * spacing);
    00372
    00373     text().draw(painter, titleRect);
    00374
    00375     painter->restore();
    00376 }
    00377
    00378 void QwtLegendItem::paintEvent(QPaintEvent *e)
    00379 {
    00380     const QRect cr = contentsRect();
    00381
    00382     QPainter painter(this);
    00383     painter.setClipRegion(e->region());
    00384
    00385     if ( d_data->isDown )
    00386     {
    00387         qDrawWinButton(&painter, 0, 0, width(), height(),
    00388 #if QT_VERSION < 0x040000
    00389             colorGroup(),
    00390 #else
    00391             palette(),
    00392 #endif
    00393             true);
    00394     }
    00395
    00396     painter.save();
    00397
    00398     if ( d_data->isDown )
    00399     {
    00400         const QSize shiftSize = buttonShift(this);
    00401         painter.translate(shiftSize.width(), shiftSize.height());
    00402     }
    00403
    00404     painter.setClipRect(cr);
    00405
    00406     drawContents(&painter);
    00407
    00408     QRect rect = cr;
    00409     rect.setX(rect.x() + margin());
    00410     if ( d_data->itemMode != QwtLegend::ReadOnlyItem )
    00411         rect.setX(rect.x() + ButtonFrame);
    00412
    00413     rect.setWidth(d_data->identifierWidth);
    00414
    00415     drawIdentifier(&painter, rect);
    00416
    00417     painter.restore();
    00418 }
    00419
    00420 void QwtLegendItem::mousePressEvent(QMouseEvent *e)
    00421 {
    00422     if ( e->button() != Qt::LeftButton )
    00423         return;
    00424
    00425     switch(d_data->itemMode)
    00426     {
    00427         case QwtLegend::ClickableItem:
    00428         {
    00429             setDown(true);
    00430             break;
    00431         }
    00432         case QwtLegend::CheckableItem:
    00433         {
    00434             setDown(!isDown());
    00435             break;
    00436         }
    00437         default:;
    00438     }
    00439 }
    00440
    00441 void QwtLegendItem::mouseReleaseEvent(QMouseEvent *e)
    00442 {
    00443     if ( !e->button() == Qt::LeftButton )
    00444         return;
    00445
    00446     if ( d_data->itemMode == QwtLegend::ClickableItem )
    00447         setDown(false);
    00448 }
    00449
    00450 void QwtLegendItem::keyPressEvent(QKeyEvent *e)
    00451 {
    00452     if ( e->key() != Qt::Key_Space || e->isAutoRepeat() )
    00453         return;
    00454
    00455     switch(d_data->itemMode)
    00456     {
    00457         case QwtLegend::ClickableItem:
    00458         {
    00459             setDown(true);
    00460             break;
    00461         }
    00462         case QwtLegend::CheckableItem:
    00463         {
    00464             setDown(!isDown());
    00465             break;
    00466         }
    00467         default:;
    00468     }
    00469 }
    00470
    00471 void QwtLegendItem::keyReleaseEvent(QKeyEvent *e)
    00472 {
    00473     if ( e->key() != Qt::Key_Space || e->isAutoRepeat() )
    00474         return;
    00475
    00476     if ( d_data->itemMode == QwtLegend::ClickableItem )
    00477         setDown(false);
    00478 }
    00479
    00480 void QwtLegendItem::setChecked(bool on)
    00481 {
    00482     if ( d_data->itemMode == QwtLegend::CheckableItem )
    00483     {
    00484         const bool isBlocked = signalsBlocked();
    00485         blockSignals(true);
    00486
    00487         setDown(on);
    00488
    00489         blockSignals(isBlocked);
    00490     }
    00491 }
    00492
    00493 bool QwtLegendItem::isChecked() const
    00494 {
    00495     return d_data->itemMode == QwtLegend::CheckableItem && isDown();
    00496 }
    00497
    00498 void QwtLegendItem::setDown(bool down)
    00499 {
    00500     if ( down == d_data->isDown )
    00501         return;
    00502
    00503     d_data->isDown = down;
    00504     update();
    00505
    00506     if ( d_data->itemMode == QwtLegend::ClickableItem )
    00507     {
    00508         if ( d_data->isDown )
    00509             emit pressed();
    00510         else
    00511         {
    00512             emit released();
    00513             emit clicked();
    00514         }
    00515     }
    00516
    00517     if ( d_data->itemMode == QwtLegend::CheckableItem )
    00518         emit checked(d_data->isDown);
    00519 }
    00520
    00521 bool QwtLegendItem::isDown() const
    00522 {
    00523     return d_data->isDown;
    00524 }
    00525
    00526 QSize QwtLegendItem::sizeHint() const
    00527 {
    00528     QSize sz = QwtTextLabel::sizeHint();
    00529     if ( d_data->itemMode != QwtLegend::ReadOnlyItem )
    00530         sz += buttonShift(this);
    00531
    00532     return sz;
    00533 }
    00534
    00535 void QwtLegendItem::drawText(QPainter *painter, const QRect &rect)
    00536 {
    00537     QwtTextLabel::drawText(painter, rect);
    00538 }