diff options
Diffstat (limited to 'src/libpcp_qwt/src/qwt_arrow_button.cpp')
-rw-r--r-- | src/libpcp_qwt/src/qwt_arrow_button.cpp | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/src/libpcp_qwt/src/qwt_arrow_button.cpp b/src/libpcp_qwt/src/qwt_arrow_button.cpp new file mode 100644 index 0000000..f451b44 --- /dev/null +++ b/src/libpcp_qwt/src/qwt_arrow_button.cpp @@ -0,0 +1,332 @@ +/* -*- 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 + *****************************************************************************/ + +#include "qwt_arrow_button.h" +#include "qwt_math.h" +#include <qpainter.h> +#include <qstyle.h> +#include <qstyleoption.h> +#include <qevent.h> +#include <qapplication.h> + +static const int MaxNum = 3; +static const int Margin = 2; +static const int Spacing = 1; + +class QwtArrowButton::PrivateData +{ +public: + int num; + Qt::ArrowType arrowType; +}; + +static QStyleOptionButton styleOpt( const QwtArrowButton* btn ) +{ + QStyleOptionButton option; + option.init( btn ); + option.features = QStyleOptionButton::None; + if ( btn->isFlat() ) + option.features |= QStyleOptionButton::Flat; + if ( btn->menu() ) + option.features |= QStyleOptionButton::HasMenu; + if ( btn->autoDefault() || btn->isDefault() ) + option.features |= QStyleOptionButton::AutoDefaultButton; + if ( btn->isDefault() ) + option.features |= QStyleOptionButton::DefaultButton; + if ( btn->isDown() ) + option.state |= QStyle::State_Sunken; + if ( !btn->isFlat() && !btn->isDown() ) + option.state |= QStyle::State_Raised; + + return option; +} + +/*! + \param num Number of arrows + \param arrowType see Qt::ArowType in the Qt docs. + \param parent Parent widget +*/ +QwtArrowButton::QwtArrowButton( int num, + Qt::ArrowType arrowType, QWidget *parent ): + QPushButton( parent ) +{ + d_data = new PrivateData; + d_data->num = qBound( 1, num, MaxNum ); + d_data->arrowType = arrowType; + + setAutoRepeat( true ); + setAutoDefault( false ); + + switch ( d_data->arrowType ) + { + case Qt::LeftArrow: + case Qt::RightArrow: + setSizePolicy( QSizePolicy::Expanding, + QSizePolicy::Fixed ); + break; + default: + setSizePolicy( QSizePolicy::Fixed, + QSizePolicy::Expanding ); + } +} + +//! Destructor +QwtArrowButton::~QwtArrowButton() +{ + delete d_data; + d_data = NULL; +} + +/*! + \brief The direction of the arrows +*/ +Qt::ArrowType QwtArrowButton::arrowType() const +{ + return d_data->arrowType; +} + +/*! + \brief The number of arrows +*/ +int QwtArrowButton::num() const +{ + return d_data->num; +} + +/*! + \return the bounding rect for the label +*/ +QRect QwtArrowButton::labelRect() const +{ + const int m = Margin; + + QRect r = rect(); + r.setRect( r.x() + m, r.y() + m, + r.width() - 2 * m, r.height() - 2 * m ); + + if ( isDown() ) + { + QStyleOptionButton option = styleOpt( this ); + const int ph = style()->pixelMetric( + QStyle::PM_ButtonShiftHorizontal, &option, this ); + const int pv = style()->pixelMetric( + QStyle::PM_ButtonShiftVertical, &option, this ); + + r.translate( ph, pv ); + } + + return r; +} + +/*! + Paint event handler + \param event Paint event +*/ +void QwtArrowButton::paintEvent( QPaintEvent *event ) +{ + QPushButton::paintEvent( event ); + QPainter painter( this ); + drawButtonLabel( &painter ); +} + +/*! + \brief Draw the button label + + \param painter Painter + \sa The Qt Manual on QPushButton +*/ +void QwtArrowButton::drawButtonLabel( QPainter *painter ) +{ + const bool isVertical = d_data->arrowType == Qt::UpArrow || + d_data->arrowType == Qt::DownArrow; + + const QRect r = labelRect(); + QSize boundingSize = labelRect().size(); + if ( isVertical ) + boundingSize.transpose(); + + const int w = + ( boundingSize.width() - ( MaxNum - 1 ) * Spacing ) / MaxNum; + + QSize arrow = arrowSize( Qt::RightArrow, + QSize( w, boundingSize.height() ) ); + + if ( isVertical ) + arrow.transpose(); + + QRect contentsSize; // aligned rect where to paint all arrows + if ( d_data->arrowType == Qt::LeftArrow || d_data->arrowType == Qt::RightArrow ) + { + contentsSize.setWidth( d_data->num * arrow.width() + + ( d_data->num - 1 ) * Spacing ); + contentsSize.setHeight( arrow.height() ); + } + else + { + contentsSize.setWidth( arrow.width() ); + contentsSize.setHeight( d_data->num * arrow.height() + + ( d_data->num - 1 ) * Spacing ); + } + + QRect arrowRect( contentsSize ); + arrowRect.moveCenter( r.center() ); + arrowRect.setSize( arrow ); + + painter->save(); + for ( int i = 0; i < d_data->num; i++ ) + { + drawArrow( painter, arrowRect, d_data->arrowType ); + + int dx = 0; + int dy = 0; + + if ( isVertical ) + dy = arrow.height() + Spacing; + else + dx = arrow.width() + Spacing; + + arrowRect.translate( dx, dy ); + } + painter->restore(); + + if ( hasFocus() ) + { + QStyleOptionFocusRect option; + option.init( this ); + option.backgroundColor = palette().color( QPalette::Window ); + + style()->drawPrimitive( QStyle::PE_FrameFocusRect, + &option, painter, this ); + } +} + +/*! + Draw an arrow int a bounding rect + + \param painter Painter + \param r Rectangle where to paint the arrow + \param arrowType Arrow type +*/ +void QwtArrowButton::drawArrow( QPainter *painter, + const QRect &r, Qt::ArrowType arrowType ) const +{ + QPolygon pa( 3 ); + + switch ( arrowType ) + { + case Qt::UpArrow: + pa.setPoint( 0, r.bottomLeft() ); + pa.setPoint( 1, r.bottomRight() ); + pa.setPoint( 2, r.center().x(), r.top() ); + break; + case Qt::DownArrow: + pa.setPoint( 0, r.topLeft() ); + pa.setPoint( 1, r.topRight() ); + pa.setPoint( 2, r.center().x(), r.bottom() ); + break; + case Qt::RightArrow: + pa.setPoint( 0, r.topLeft() ); + pa.setPoint( 1, r.bottomLeft() ); + pa.setPoint( 2, r.right(), r.center().y() ); + break; + case Qt::LeftArrow: + pa.setPoint( 0, r.topRight() ); + pa.setPoint( 1, r.bottomRight() ); + pa.setPoint( 2, r.left(), r.center().y() ); + break; + default: + break; + } + + painter->save(); + + painter->setPen( palette().color( QPalette::ButtonText ) ); + painter->setBrush( palette().brush( QPalette::ButtonText ) ); + painter->drawPolygon( pa ); + + painter->restore(); +} + +/*! + \return a size hint +*/ +QSize QwtArrowButton::sizeHint() const +{ + const QSize hint = minimumSizeHint(); + return hint.expandedTo( QApplication::globalStrut() ); +} + +/*! + \brief Return a minimum size hint +*/ +QSize QwtArrowButton::minimumSizeHint() const +{ + const QSize asz = arrowSize( Qt::RightArrow, QSize() ); + + QSize sz( + 2 * Margin + ( MaxNum - 1 ) * Spacing + MaxNum * asz.width(), + 2 * Margin + asz.height() + ); + + if ( d_data->arrowType == Qt::UpArrow || d_data->arrowType == Qt::DownArrow ) + sz.transpose(); + + QStyleOption styleOption; + styleOption.init( this ); + + sz = style()->sizeFromContents( QStyle::CT_PushButton, + &styleOption, sz, this ); + + return sz; +} + +/*! + Calculate the size for a arrow that fits into a rect of a given size + + \param arrowType Arrow type + \param boundingSize Bounding size + \return Size of the arrow +*/ +QSize QwtArrowButton::arrowSize( Qt::ArrowType arrowType, + const QSize &boundingSize ) const +{ + QSize bs = boundingSize; + if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow ) + bs.transpose(); + + const int MinLen = 2; + const QSize sz = bs.expandedTo( + QSize( MinLen, 2 * MinLen - 1 ) ); // minimum + + int w = sz.width(); + int h = 2 * w - 1; + + if ( h > sz.height() ) + { + h = sz.height(); + w = ( h + 1 ) / 2; + } + + QSize arrSize( w, h ); + if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow ) + arrSize.transpose(); + + return arrSize; +} + +/*! + \brief autoRepeat for the space keys +*/ +void QwtArrowButton::keyPressEvent( QKeyEvent *event ) +{ + if ( event->isAutoRepeat() && event->key() == Qt::Key_Space ) + Q_EMIT clicked(); + + QPushButton::keyPressEvent( event ); +} |