Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

qwt_legend.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 <qapplication.h> 
00013 #include <qpainter.h>
00014 #include <qbitmap.h>
00015 #include <qstyle.h>
00016 #include "qwt_text.h"
00017 #include "qwt_legend.h"
00018 #include "qwt_painter.h"
00019 #include "qwt_dyngrid_layout.h"
00020 
00021 static const int IdentifierWidth = 8;
00022 static const int Margin = 2;
00023 
00025 QwtLegendItem::QwtLegendItem():
00026     d_identifierMode(ShowLine | ShowText),
00027     d_curvePen(Qt::NoPen)
00028 {
00029 }
00030 
00036 QwtLegendItem::QwtLegendItem(const QwtSymbol &symbol, const QPen &curvePen):
00037     d_identifierMode(ShowLine | ShowText),
00038     d_symbol(symbol),
00039     d_curvePen(curvePen)
00040 {
00041 }
00042 
00044 QwtLegendItem::~QwtLegendItem()
00045 {
00046 }
00047 
00055 void QwtLegendItem::setIdentifierMode(int mode) 
00056 {
00057     if ( mode != d_identifierMode )
00058     {
00059         d_identifierMode = mode;
00060         updateItem();
00061     }
00062 }
00063 
00068 int QwtLegendItem::identifierMode() const 
00069 { 
00070     return d_identifierMode; 
00071 }
00072 
00079 void QwtLegendItem::setSymbol(const QwtSymbol &symbol) 
00080 {
00081     if ( symbol != d_symbol )
00082     {
00083         d_symbol = symbol;
00084         updateItem();
00085     }
00086 }
00087     
00092 const QwtSymbol& QwtLegendItem::symbol() const 
00093 { 
00094     return d_symbol; 
00095 }
00096     
00097 
00104 void QwtLegendItem::setCurvePen(const QPen &pen) 
00105 {
00106     if ( pen != d_curvePen )
00107     {
00108         d_curvePen = pen;
00109         updateItem();
00110     }
00111 }
00112 
00117 const QPen& QwtLegendItem::curvePen() const 
00118 { 
00119     return d_curvePen; 
00120 }
00121 
00123 void QwtLegendItem::updateItem()
00124 {
00125 }
00126 
00132 void QwtLegendItem::drawIdentifier(
00133     QPainter *painter, const QRect &rect) const
00134 {
00135     if ( rect.isEmpty() )
00136         return;
00137 
00138     if ( (d_identifierMode & ShowLine ) && (d_curvePen.style() != Qt::NoPen) )
00139     {
00140         painter->save();
00141         painter->setPen(d_curvePen);
00142         QwtPainter::drawLine(painter, rect.left(), rect.center().y(), 
00143             rect.right(), rect.center().y());
00144         painter->restore();
00145     }
00146 
00147     if ( (d_identifierMode & ShowSymbol) 
00148         && (d_symbol.style() != QwtSymbol::None) )
00149     {
00150         QSize symbolSize = 
00151             QwtPainter::metricsMap().screenToLayout(d_symbol.size());
00152 
00153         // scale the symbol size down if it doesn't fit into rect.
00154 
00155         if ( rect.width() < symbolSize.width() )
00156         {
00157             const double ratio = 
00158                 double(symbolSize.width()) / double(rect.width());
00159             symbolSize.setWidth(rect.width());
00160             symbolSize.setHeight(qRound(symbolSize.height() / ratio));
00161         }
00162         if ( rect.height() < symbolSize.height() )
00163         {
00164             const double ratio = 
00165                 double(symbolSize.width()) / double(rect.width());
00166             symbolSize.setHeight(rect.height());
00167             symbolSize.setWidth(qRound(symbolSize.width() / ratio));
00168         }
00169 
00170         QRect symbolRect;
00171         symbolRect.setSize(symbolSize);
00172         symbolRect.moveCenter(rect.center());
00173 
00174         painter->save();
00175         painter->setBrush(d_symbol.brush());
00176         painter->setPen(d_symbol.pen());
00177         d_symbol.draw(painter, symbolRect);
00178         painter->restore();
00179     }
00180 }
00181 
00188 void QwtLegendItem::drawItem(QPainter *painter, const QRect &rect) const
00189 {
00190     const QwtMetricsMap &map = QwtPainter::metricsMap();
00191 
00192     const int margin = map.screenToLayoutX(Margin);
00193 
00194     const QRect identifierRect(rect.x() + margin, rect.y(), 
00195         map.screenToLayoutX(IdentifierWidth), rect.height());
00196     drawIdentifier(painter, identifierRect);
00197 
00198     // Label
00199 
00200     QwtText *txt = titleText();
00201     if ( txt )
00202     {
00203         QRect titleRect = rect;
00204         titleRect.setX(identifierRect.right() + 2 * margin);
00205      
00206         txt->draw(painter, titleRect);
00207         delete txt;
00208     }
00209 }
00210 
00211 
00216 QwtLegendButton::QwtLegendButton(QWidget *parent, const char *name): 
00217     QwtPushButton(parent, name)
00218 {
00219     init();
00220 }
00221     
00229 QwtLegendButton::QwtLegendButton(
00230         const QwtSymbol &symbol, const QPen &curvePen, const QString &text,
00231         QWidget *parent, const char *name): 
00232     QwtPushButton(text, parent, name),
00233     QwtLegendItem(symbol, curvePen)
00234 {
00235     init();
00236 }
00237 
00238 void QwtLegendButton::init()
00239 {
00240     setFlat(TRUE);
00241     setAlignment(Qt::AlignLeft | Qt::AlignVCenter | 
00242         Qt::ExpandTabs | Qt::WordBreak);
00243     setIndent(2 * Margin);
00244     updateIconset();
00245 }
00246 
00247 void QwtLegendButton::updateItem()
00248 {
00249     updateIconset();
00250 }
00251 
00255 void QwtLegendButton::updateIconset()
00256 {
00257     const QFontMetrics fm(font());
00258 
00259     QPixmap pm(IdentifierWidth, fm.height());
00260     pm.fill(this, 0, 0);
00261 
00262     QPainter p(&pm);
00263     drawIdentifier(&p, QRect(0, 0, pm.width(), pm.height()) );
00264     p.end();
00265 
00266     pm.setMask(pm.createHeuristicMask());
00267 
00268     setIconSet(QIconSet(pm));
00269 }
00270 
00277 void QwtLegendButton::setTitle(const QString &title)
00278 {
00279     setText(title);
00280 }
00281 
00286 QString QwtLegendButton::title() const
00287 {
00288     return text();
00289 }
00290 
00295 QwtText *QwtLegendButton::titleText() const
00296 {
00297     return QwtText::makeText(text(), usedTextFormat(),
00298         alignment(), font());
00299 }
00300 
00305 QwtLegendLabel::QwtLegendLabel(QWidget *parent, const char *name):
00306     QLabel(parent, name)
00307 {
00308     init();
00309 }
00310 
00318 QwtLegendLabel::QwtLegendLabel(const QwtSymbol &symbol, 
00319         const QPen &curvePen, const QString &text, 
00320         QWidget *parent, const char *name):
00321     QLabel(text, parent, name),
00322     QwtLegendItem(symbol, curvePen)
00323 {
00324     init();
00325 }
00326 
00327 void QwtLegendLabel::init()
00328 {
00329     setAlignment(Qt::AlignLeft | Qt::AlignVCenter | 
00330         Qt::ExpandTabs | Qt::WordBreak);
00331     setIndent(Margin + IdentifierWidth + 2 * Margin);
00332     setMargin(Margin);
00333 }
00334 
00341 void QwtLegendLabel::setTitle(const QString &title)
00342 {
00343     setText(title);
00344 }
00345 
00350 QString QwtLegendLabel::title() const
00351 {
00352     return text();
00353 }
00354 
00359 QwtText *QwtLegendLabel::titleText() const
00360 {
00361     return QwtText::makeText(text(), textFormat(), 
00362         alignment(), font());
00363 }
00364 
00368 void QwtLegendLabel::drawContents(QPainter *painter)
00369 {
00370     QLabel::drawContents(painter);
00371 
00372     QRect rect = contentsRect();
00373     rect.setX(rect.x() + Margin);
00374     rect.setWidth(IdentifierWidth);
00375 
00376     drawIdentifier(painter, rect);
00377 }
00378 
00379 void QwtLegendLabel::updateItem()
00380 {
00381     update();
00382 }
00383 
00388 QwtLegend::QwtLegend(QWidget *parent, const char *name): 
00389     QScrollView(parent, name),
00390     d_readOnly(FALSE),
00391     d_displayPolicy(QwtLegend::Auto),
00392     d_identifierMode(QwtLegendButton::ShowLine
00393              | QwtLegendButton::ShowSymbol
00394              | QwtLegendButton::ShowText)
00395 {
00396     setFrameStyle(NoFrame);
00397     setResizePolicy(Manual);
00398 
00399     viewport()->setBackgroundMode(NoBackground); // Avoid flicker
00400 
00401     d_contentsWidget = new QWidget(viewport());
00402     d_contentsWidget->installEventFilter(this);
00403 
00404     QwtDynGridLayout *layout = new QwtDynGridLayout(d_contentsWidget);
00405     layout->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
00406     layout->setAutoAdd(TRUE);
00407 
00408     addChild(d_contentsWidget);
00409 }
00410 
00415 void QwtLegend::setReadOnly(bool readOnly)
00416 {
00417     d_readOnly = readOnly;
00418 }
00419 
00424 bool QwtLegend::isReadOnly() const
00425 {
00426     return d_readOnly;
00427 }
00428 
00437 void QwtLegend::setDisplayPolicy(LegendDisplayPolicy policy, int mode)
00438 {
00439     d_displayPolicy = policy;
00440     if (-1 != mode)
00441        d_identifierMode = mode;
00442 }
00443 
00450 QwtLegend::LegendDisplayPolicy QwtLegend::displayPolicy() const 
00451 { 
00452     return d_displayPolicy; 
00453 }
00454 
00462 int QwtLegend::identifierMode() const
00463 {
00464     return d_identifierMode;
00465 }
00466 
00471 QWidget *QwtLegend::contentsWidget() 
00472 { 
00473     return d_contentsWidget; 
00474 }
00475 
00481 const QWidget *QwtLegend::contentsWidget() const 
00482 { 
00483     return d_contentsWidget; 
00484 }
00485 
00493 void QwtLegend::insertItem(QWidget *item, long key)
00494 {
00495     if ( item == NULL || key < 0 )
00496         return;
00497 
00498     if ( item->parent() != d_contentsWidget )
00499         item->reparent(d_contentsWidget, QPoint(0, 0));
00500 
00501     item->show();
00502 
00503     if ( d_items.count() > d_items.size() - 5 )
00504         d_items.resize(d_items.count() + 5);
00505 
00506     d_items.insert(key, item);
00507 
00508     layoutContents();
00509 
00510     QWidget *w = 0;
00511 
00512     if ( d_contentsWidget->layout() )
00513     {
00514         // set tab focus chain
00515 
00516         QLayoutIterator layoutIterator = 
00517             d_contentsWidget->layout()->iterator();
00518 
00519         for ( QLayoutItem *item = layoutIterator.current();
00520             item != 0; item = ++layoutIterator)
00521         {
00522             if ( w && item->widget() )
00523                 QWidget::setTabOrder(w, item->widget());
00524 
00525             w = item->widget();
00526         }
00527     }
00528 }
00529 
00531 QWidget *QwtLegend::findItem(long key)
00532 {
00533     return d_items.find(key);
00534 }
00535 
00537 const QWidget *QwtLegend::findItem(long key) const 
00538 { 
00539     return d_items.find(key); 
00540 }
00541     
00543 QWidget *QwtLegend::takeItem(long key) 
00544 { 
00545     return d_items.take(key); 
00546 }
00547 
00553 long QwtLegend::key(const QWidget *item) const
00554 {
00555     QWidgetIntDictIt it(d_items);
00556     for ( const QWidget *w = it.toFirst(); w != 0; w = ++it)
00557     {
00558         if ( w == item )
00559             return it.currentKey();
00560     }
00561     return -1;
00562 }
00563 
00565 void QwtLegend::clear()
00566 {
00567     // We can't delete the items while we are running
00568     // through the iterator. So we collect them in
00569     // a list first.
00570 
00571     QValueList<QWidget *> clearList;
00572     
00573     QWidgetIntDictIt it(d_items);
00574     for ( QWidget *item = it.toFirst(); item != 0; item = ++it)
00575         clearList += item;
00576 
00577     for ( uint i = 0; i < clearList.count(); i++ )
00578         delete clearList[i];
00579 
00580 #if QT_VERSION < 232
00581     // In Qt 2.3.0 the ChildRemoved events are not sent, before the
00582     // first show of the legend. Thus the deleted items are not cleared
00583     // from the list in QwtLegend::eventFilter. In most cases
00584     // the following clear is useless, but is is safe to do so.
00585     
00586     d_items.clear();
00587 #endif
00588 }
00589 
00591 QWidgetIntDictIt QwtLegend::itemIterator() const
00592 {
00593     return QWidgetIntDictIt(d_items);
00594 }
00595 
00597 QSize QwtLegend::sizeHint() const
00598 {
00599     QSize hint = d_contentsWidget->sizeHint();
00600     hint += QSize(2 * frameWidth(), 2 * frameWidth());
00601     
00602     return hint;
00603 }
00604 
00608 int QwtLegend::heightForWidth(int w) const
00609 {
00610     w -= 2 * frameWidth();
00611 
00612     int h = d_contentsWidget->heightForWidth(w);
00613     if ( h <= 0 ) // not implemented, we try the layout
00614     {
00615         QLayout *l = d_contentsWidget->layout();
00616         if ( l && l->hasHeightForWidth() )
00617         {
00618             h = l->heightForWidth(w);
00619             h += 2 * frameWidth();
00620         }
00621     }
00622 
00623     return h;
00624 }
00625 
00629 void QwtLegend::layoutContents()
00630 {
00631     const QSize visibleSize = viewport()->size();
00632 
00633     const QLayout *l = d_contentsWidget->layout();
00634     if ( l && l->inherits("QwtDynGridLayout") )
00635     {
00636         const QwtDynGridLayout *tl = (const QwtDynGridLayout *)l;
00637 
00638         const int minW = int(tl->maxItemWidth()) + 2 * tl->margin();
00639 
00640         int w = QMAX(visibleSize.width(), minW);
00641         int h = QMAX(tl->heightForWidth(w), visibleSize.height());
00642 
00643         const int vpWidth = viewportSize(w, h).width();
00644 
00645         if ( w > vpWidth )
00646         {
00647             w = QMAX(vpWidth, minW);
00648             h = QMAX(tl->heightForWidth(w), visibleSize.height());
00649         }
00650 
00651         d_contentsWidget->resize(w, h);
00652         resizeContents(w, h);
00653     }
00654 }
00655 
00656 /*
00657   Filter QEvent::ChildRemoved, and QEvent::LayoutHint for
00658   QwtLegend::contentsWidget().
00659 */
00660 
00662 bool QwtLegend::eventFilter(QObject *o, QEvent *e)
00663 {
00664     if ( o == d_contentsWidget )
00665     {
00666         switch(e->type())
00667         {
00668             case QEvent::ChildRemoved:
00669             {   
00670                 const QChildEvent *ce = (const QChildEvent *)e;
00671                 if ( ce->child()->isWidgetType() )
00672                     (void)takeItem(key((QWidget *)ce->child()));
00673                 break;
00674             }
00675             case QEvent::LayoutHint:
00676             {
00677                 layoutContents();
00678                 break;
00679             }
00680             default:
00681                 break;
00682         }
00683     }
00684     
00685     return QScrollView::eventFilter(o, e);
00686 }
00687 
00692 void QwtLegend::viewportResizeEvent(QResizeEvent *e)
00693 {
00694     QScrollView::viewportResizeEvent(e);
00695 
00696     // It's not safe to update the layout now, because
00697     // we are in an internal update of the scrollview framework.
00698     // So we delay the update by posting a LayoutHint.
00699 
00700     QApplication::postEvent(d_contentsWidget, new QEvent(QEvent::LayoutHint));
00701 }

Generated on Sun Nov 21 11:12:43 2004 for Qwt User's Guide by doxygen 1.3.5