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 Tue Nov 16 21:12:20 2004 for Qwt User's Guide by doxygen 1.3.8