/* -*- mode: C++ ; c-file-style: "stroustrup" -*- ***************************** * Qwt Widget Library * Copyright (C) 1997 Josef Wilgen * Copyright (C) 2002 Uwe Rathmann * * This library is free software; you can redistribute it and/or * modify it under the terms of the Qwt License, Version 1.0 *****************************************************************************/ // vim: expandtab #include #include #include #include #if QT_VERSION >= 0x040000 #include #include #endif #include "qwt_math.h" #include "qwt_painter.h" #include "qwt_symbol.h" #include "qwt_legend_item.h" static const int ButtonFrame = 2; static const int Margin = 2; static QSize buttonShift(const QwtLegendItem *w) { #if QT_VERSION < 0x040000 const int ph = w->style().pixelMetric( QStyle::PM_ButtonShiftHorizontal, w); const int pv = w->style().pixelMetric( QStyle::PM_ButtonShiftVertical, w); #else QStyleOption option; option.init(w); const int ph = w->style()->pixelMetric( QStyle::PM_ButtonShiftHorizontal, &option, w); const int pv = w->style()->pixelMetric( QStyle::PM_ButtonShiftVertical, &option, w); #endif return QSize(ph, pv); } class QwtLegendItem::PrivateData { public: PrivateData(): itemMode(QwtLegend::ReadOnlyItem), isDown(false), identifierWidth(8), identifierMode(QwtLegendItem::ShowLine | QwtLegendItem::ShowText), curvePen(Qt::NoPen), spacing(Margin) { symbol = new QwtSymbol(); } ~PrivateData() { delete symbol; } QwtLegend::LegendItemMode itemMode; bool isDown; int identifierWidth; int identifierMode; QwtSymbol *symbol; QPen curvePen; int spacing; }; /*! \param parent Parent widget */ QwtLegendItem::QwtLegendItem(QWidget *parent): QwtTextLabel(parent) { d_data = new PrivateData; init(QwtText()); } /*! \param symbol Curve symbol \param curvePen Curve pen \param text Label text \param parent Parent widget */ QwtLegendItem::QwtLegendItem(const QwtSymbol &symbol, const QPen &curvePen, const QwtText &text, QWidget *parent): QwtTextLabel(parent) { d_data = new PrivateData; delete d_data->symbol; d_data->symbol = symbol.clone(); d_data->curvePen = curvePen; init(text); } void QwtLegendItem::init(const QwtText &text) { setMargin(Margin); setIndent(margin() + d_data->identifierWidth + 2 * d_data->spacing); setText(text); } //! Destructor QwtLegendItem::~QwtLegendItem() { delete d_data; d_data = NULL; } /*! Set the text to the legend item \param text Text label \sa QwtTextLabel::text() */ void QwtLegendItem::setText(const QwtText &text) { const int flags = Qt::AlignLeft | Qt::AlignVCenter #if QT_VERSION < 0x040000 | Qt::WordBreak | Qt::ExpandTabs; #else | Qt::TextExpandTabs | Qt::TextWordWrap; #endif QwtText txt = text; txt.setRenderFlags(flags); QwtTextLabel::setText(txt); } /*! Set the item mode The default is QwtLegend::ReadOnlyItem \param mode Item mode \sa itemMode() */ void QwtLegendItem::setItemMode(QwtLegend::LegendItemMode mode) { d_data->itemMode = mode; d_data->isDown = false; #if QT_VERSION >= 0x040000 using namespace Qt; #endif setFocusPolicy(mode != QwtLegend::ReadOnlyItem ? TabFocus : NoFocus); setMargin(ButtonFrame + Margin); updateGeometry(); } /*! Return the item mode \sa setItemMode() */ QwtLegend::LegendItemMode QwtLegendItem::itemMode() const { return d_data->itemMode; } /*! Set identifier mode. Default is ShowLine | ShowText. \param mode Or'd values of IdentifierMode \sa identifierMode() */ void QwtLegendItem::setIdentifierMode(int mode) { if ( mode != d_data->identifierMode ) { d_data->identifierMode = mode; update(); } } /*! Or'd values of IdentifierMode. \sa setIdentifierMode(), IdentifierMode */ int QwtLegendItem::identifierMode() const { return d_data->identifierMode; } /*! Set the width for the identifier Default is 8 pixels \param width New width \sa identifierMode(), identifierWidth */ void QwtLegendItem::setIdentfierWidth(int width) { width = qwtMax(width, 0); if ( width != d_data->identifierWidth ) { d_data->identifierWidth = width; setIndent(margin() + d_data->identifierWidth + 2 * d_data->spacing); } } /*! Return the width of the identifier \sa setIdentfierWidth */ int QwtLegendItem::identifierWidth() const { return d_data->identifierWidth; } /*! Change the spacing \param spacing Spacing \sa spacing(), identifierWidth(), QwtTextLabel::margin() */ void QwtLegendItem::setSpacing(int spacing) { spacing = qwtMax(spacing, 0); if ( spacing != d_data->spacing ) { d_data->spacing = spacing; setIndent(margin() + d_data->identifierWidth + 2 * d_data->spacing); } } /*! Return the spacing \sa setSpacing(), identifierWidth(), QwtTextLabel::margin() */ int QwtLegendItem::spacing() const { return d_data->spacing; } /*! Set curve symbol. \param symbol Symbol \sa symbol() */ void QwtLegendItem::setSymbol(const QwtSymbol &symbol) { delete d_data->symbol; d_data->symbol = symbol.clone(); update(); } /*! \return The curve symbol. \sa setSymbol() */ const QwtSymbol& QwtLegendItem::symbol() const { return *d_data->symbol; } /*! Set curve pen. \param pen Curve pen \sa curvePen() */ void QwtLegendItem::setCurvePen(const QPen &pen) { if ( pen != d_data->curvePen ) { d_data->curvePen = pen; update(); } } /*! \return The curve pen. \sa setCurvePen() */ const QPen& QwtLegendItem::curvePen() const { return d_data->curvePen; } /*! Paint the identifier to a given rect. \param painter Painter \param rect Rect where to paint */ void QwtLegendItem::drawIdentifier( QPainter *painter, const QRect &rect) const { if ( rect.isEmpty() ) return; if ( (d_data->identifierMode & ShowLine ) && (d_data->curvePen.style() != Qt::NoPen) ) { painter->save(); painter->setPen(d_data->curvePen); QwtPainter::drawLine(painter, rect.left(), rect.center().y(), rect.right(), rect.center().y()); painter->restore(); } if ( (d_data->identifierMode & ShowSymbol) && (d_data->symbol->style() != QwtSymbol::NoSymbol) ) { QSize symbolSize = QwtPainter::metricsMap().screenToLayout(d_data->symbol->size()); // scale the symbol size down if it doesn't fit into rect. if ( rect.width() < symbolSize.width() ) { const double ratio = double(symbolSize.width()) / double(rect.width()); symbolSize.setWidth(rect.width()); symbolSize.setHeight(qRound(symbolSize.height() / ratio)); } if ( rect.height() < symbolSize.height() ) { const double ratio = double(symbolSize.width()) / double(rect.width()); symbolSize.setHeight(rect.height()); symbolSize.setWidth(qRound(symbolSize.width() / ratio)); } QRect symbolRect; symbolRect.setSize(symbolSize); symbolRect.moveCenter(rect.center()); painter->save(); painter->setBrush(d_data->symbol->brush()); painter->setPen(d_data->symbol->pen()); d_data->symbol->draw(painter, symbolRect); painter->restore(); } } /*! Draw the legend item to a given rect. \param painter Painter \param rect Rect where to paint the button */ void QwtLegendItem::drawItem(QPainter *painter, const QRect &rect) const { painter->save(); const QwtMetricsMap &map = QwtPainter::metricsMap(); const int m = map.screenToLayoutX(margin()); const int spacing = map.screenToLayoutX(d_data->spacing); const int identifierWidth = map.screenToLayoutX(d_data->identifierWidth); const QRect identifierRect(rect.x() + m, rect.y(), identifierWidth, rect.height()); drawIdentifier(painter, identifierRect); // Label QRect titleRect = rect; titleRect.setX(identifierRect.right() + 2 * spacing); text().draw(painter, titleRect); painter->restore(); } //! Paint event void QwtLegendItem::paintEvent(QPaintEvent *e) { const QRect cr = contentsRect(); QPainter painter(this); painter.setClipRegion(e->region()); if ( d_data->isDown ) { qDrawWinButton(&painter, 0, 0, width(), height(), #if QT_VERSION < 0x040000 colorGroup(), #else palette(), #endif true); } painter.save(); if ( d_data->isDown ) { const QSize shiftSize = buttonShift(this); painter.translate(shiftSize.width(), shiftSize.height()); } painter.setClipRect(cr); drawContents(&painter); QRect rect = cr; rect.setX(rect.x() + margin()); if ( d_data->itemMode != QwtLegend::ReadOnlyItem ) rect.setX(rect.x() + ButtonFrame); rect.setWidth(d_data->identifierWidth); drawIdentifier(&painter, rect); painter.restore(); } //! Handle mouse press events void QwtLegendItem::mousePressEvent(QMouseEvent *e) { if ( e->button() == Qt::LeftButton ) { switch(d_data->itemMode) { case QwtLegend::ClickableItem: { setDown(true); return; } case QwtLegend::CheckableItem: { setDown(!isDown()); return; } default: ; } } QwtTextLabel::mousePressEvent(e); } //! Handle mouse release events void QwtLegendItem::mouseReleaseEvent(QMouseEvent *e) { if ( e->button() == Qt::LeftButton ) { switch(d_data->itemMode) { case QwtLegend::ClickableItem: { setDown(false); return; } case QwtLegend::CheckableItem: { return; // do nothing, but accept } default: ; } } QwtTextLabel::mouseReleaseEvent(e); } //! Handle key press events void QwtLegendItem::keyPressEvent(QKeyEvent *e) { if ( e->key() == Qt::Key_Space ) { switch(d_data->itemMode) { case QwtLegend::ClickableItem: { if ( !e->isAutoRepeat() ) setDown(true); return; } case QwtLegend::CheckableItem: { if ( !e->isAutoRepeat() ) setDown(!isDown()); return; } default: ; } } QwtTextLabel::keyPressEvent(e); } //! Handle key release events void QwtLegendItem::keyReleaseEvent(QKeyEvent *e) { if ( e->key() == Qt::Key_Space ) { switch(d_data->itemMode) { case QwtLegend::ClickableItem: { if ( !e->isAutoRepeat() ) setDown(false); return; } case QwtLegend::CheckableItem: { return; // do nothing, but accept } default: ; } } QwtTextLabel::keyReleaseEvent(e); } /*! Check/Uncheck a the item \param on check/uncheck \sa setItemMode() */ void QwtLegendItem::setChecked(bool on) { if ( d_data->itemMode == QwtLegend::CheckableItem ) { const bool isBlocked = signalsBlocked(); blockSignals(true); setDown(on); blockSignals(isBlocked); } } //! Return true, if the item is checked bool QwtLegendItem::isChecked() const { return d_data->itemMode == QwtLegend::CheckableItem && isDown(); } //! Set the item being down void QwtLegendItem::setDown(bool down) { if ( down == d_data->isDown ) return; d_data->isDown = down; update(); if ( d_data->itemMode == QwtLegend::ClickableItem ) { if ( d_data->isDown ) emit pressed(); else { emit released(); emit clicked(); } } if ( d_data->itemMode == QwtLegend::CheckableItem ) emit checked(d_data->isDown); } //! Return true, if the item is down bool QwtLegendItem::isDown() const { return d_data->isDown; } //! Return a size hint QSize QwtLegendItem::sizeHint() const { QSize sz = QwtTextLabel::sizeHint(); if ( d_data->itemMode != QwtLegend::ReadOnlyItem ) sz += buttonShift(this); return sz; } void QwtLegendItem::drawText(QPainter *painter, const QRect &rect) { QwtTextLabel::drawText(painter, rect); }