qwt_arrow_button.cpp
Go to the documentation of this file.
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 #include "qwt_arrow_button.h"
00011 #include "qwt_math.h"
00012 #include <qpainter.h>
00013 #include <qstyle.h>
00014 #include <qstyleoption.h>
00015 #include <qevent.h>
00016 #include <qapplication.h>
00017 
00018 static const int MaxNum = 3;
00019 static const int Margin = 2;
00020 static const int Spacing = 1;
00021 
00022 class QwtArrowButton::PrivateData
00023 {
00024 public:
00025     int num;
00026     Qt::ArrowType arrowType;
00027 };
00028 
00029 static QStyleOptionButton styleOpt( const QwtArrowButton* btn )
00030 {
00031     QStyleOptionButton option;
00032     option.init( btn );
00033     option.features = QStyleOptionButton::None;
00034     if ( btn->isFlat() )
00035         option.features |= QStyleOptionButton::Flat;
00036     if ( btn->menu() )
00037         option.features |= QStyleOptionButton::HasMenu;
00038     if ( btn->autoDefault() || btn->isDefault() )
00039         option.features |= QStyleOptionButton::AutoDefaultButton;
00040     if ( btn->isDefault() )
00041         option.features |= QStyleOptionButton::DefaultButton;
00042     if ( btn->isDown() )
00043         option.state |= QStyle::State_Sunken;
00044     if ( !btn->isFlat() && !btn->isDown() )
00045         option.state |= QStyle::State_Raised;
00046 
00047     return option;
00048 }
00049 
00055 QwtArrowButton::QwtArrowButton( int num,
00056         Qt::ArrowType arrowType, QWidget *parent ):
00057     QPushButton( parent )
00058 {
00059     d_data = new PrivateData;
00060     d_data->num = qBound( 1, num, MaxNum );
00061     d_data->arrowType = arrowType;
00062 
00063     setAutoRepeat( true );
00064     setAutoDefault( false );
00065 
00066     switch ( d_data->arrowType )
00067     {
00068         case Qt::LeftArrow:
00069         case Qt::RightArrow:
00070             setSizePolicy( QSizePolicy::Expanding,
00071                 QSizePolicy::Fixed );
00072             break;
00073         default:
00074             setSizePolicy( QSizePolicy::Fixed,
00075                 QSizePolicy::Expanding );
00076     }
00077 }
00078 
00080 QwtArrowButton::~QwtArrowButton()
00081 {
00082     delete d_data;
00083     d_data = NULL;
00084 }
00085 
00089 Qt::ArrowType QwtArrowButton::arrowType() const
00090 {
00091     return d_data->arrowType;
00092 }
00093 
00097 int QwtArrowButton::num() const
00098 {
00099     return d_data->num;
00100 }
00101 
00105 QRect QwtArrowButton::labelRect() const
00106 {
00107     const int m = Margin;
00108 
00109     QRect r = rect();
00110     r.setRect( r.x() + m, r.y() + m,
00111         r.width() - 2 * m, r.height() - 2 * m );
00112 
00113     if ( isDown() )
00114     {
00115         QStyleOptionButton option = styleOpt( this );
00116         const int ph = style()->pixelMetric(
00117             QStyle::PM_ButtonShiftHorizontal, &option, this );
00118         const int pv = style()->pixelMetric(
00119             QStyle::PM_ButtonShiftVertical, &option, this );
00120 
00121         r.translate( ph, pv );
00122     }
00123 
00124     return r;
00125 }
00126 
00131 void QwtArrowButton::paintEvent( QPaintEvent *event )
00132 {
00133     QPushButton::paintEvent( event );
00134     QPainter painter( this );
00135     drawButtonLabel( &painter );
00136 }
00137 
00144 void QwtArrowButton::drawButtonLabel( QPainter *painter )
00145 {
00146     const bool isVertical = d_data->arrowType == Qt::UpArrow ||
00147         d_data->arrowType == Qt::DownArrow;
00148 
00149     const QRect r = labelRect();
00150     QSize boundingSize = labelRect().size();
00151     if ( isVertical )
00152         boundingSize.transpose();
00153 
00154     const int w =
00155         ( boundingSize.width() - ( MaxNum - 1 ) * Spacing ) / MaxNum;
00156 
00157     QSize arrow = arrowSize( Qt::RightArrow,
00158         QSize( w, boundingSize.height() ) );
00159 
00160     if ( isVertical )
00161         arrow.transpose();
00162 
00163     QRect contentsSize; // aligned rect where to paint all arrows
00164     if ( d_data->arrowType == Qt::LeftArrow || d_data->arrowType == Qt::RightArrow )
00165     {
00166         contentsSize.setWidth( d_data->num * arrow.width()
00167             + ( d_data->num - 1 ) * Spacing );
00168         contentsSize.setHeight( arrow.height() );
00169     }
00170     else
00171     {
00172         contentsSize.setWidth( arrow.width() );
00173         contentsSize.setHeight( d_data->num * arrow.height()
00174             + ( d_data->num - 1 ) * Spacing );
00175     }
00176 
00177     QRect arrowRect( contentsSize );
00178     arrowRect.moveCenter( r.center() );
00179     arrowRect.setSize( arrow );
00180 
00181     painter->save();
00182     for ( int i = 0; i < d_data->num; i++ )
00183     {
00184         drawArrow( painter, arrowRect, d_data->arrowType );
00185 
00186         int dx = 0;
00187         int dy = 0;
00188 
00189         if ( isVertical )
00190             dy = arrow.height() + Spacing;
00191         else
00192             dx = arrow.width() + Spacing;
00193 
00194         arrowRect.translate( dx, dy );
00195     }
00196     painter->restore();
00197 
00198     if ( hasFocus() )
00199     {
00200         QStyleOptionFocusRect option;
00201         option.init( this );
00202         option.backgroundColor = palette().color( QPalette::Window );
00203 
00204         style()->drawPrimitive( QStyle::PE_FrameFocusRect,
00205             &option, painter, this );
00206     }
00207 }
00208 
00216 void QwtArrowButton::drawArrow( QPainter *painter,
00217     const QRect &r, Qt::ArrowType arrowType ) const
00218 {
00219     QPolygon pa( 3 );
00220 
00221     switch ( arrowType )
00222     {
00223         case Qt::UpArrow:
00224             pa.setPoint( 0, r.bottomLeft() );
00225             pa.setPoint( 1, r.bottomRight() );
00226             pa.setPoint( 2, r.center().x(), r.top() );
00227             break;
00228         case Qt::DownArrow:
00229             pa.setPoint( 0, r.topLeft() );
00230             pa.setPoint( 1, r.topRight() );
00231             pa.setPoint( 2, r.center().x(), r.bottom() );
00232             break;
00233         case Qt::RightArrow:
00234             pa.setPoint( 0, r.topLeft() );
00235             pa.setPoint( 1, r.bottomLeft() );
00236             pa.setPoint( 2, r.right(), r.center().y() );
00237             break;
00238         case Qt::LeftArrow:
00239             pa.setPoint( 0, r.topRight() );
00240             pa.setPoint( 1, r.bottomRight() );
00241             pa.setPoint( 2, r.left(), r.center().y() );
00242             break;
00243         default:
00244             break;
00245     }
00246 
00247     painter->save();
00248 
00249     painter->setRenderHint( QPainter::Antialiasing, true );
00250     painter->setPen( Qt::NoPen );
00251     painter->setBrush( palette().brush( QPalette::ButtonText ) );
00252     painter->drawPolygon( pa );
00253 
00254     painter->restore();
00255 }
00256 
00260 QSize QwtArrowButton::sizeHint() const
00261 {
00262     const QSize hint = minimumSizeHint();
00263     return hint.expandedTo( QApplication::globalStrut() );
00264 }
00265 
00269 QSize QwtArrowButton::minimumSizeHint() const
00270 {
00271     const QSize asz = arrowSize( Qt::RightArrow, QSize() );
00272 
00273     QSize sz(
00274         2 * Margin + ( MaxNum - 1 ) * Spacing + MaxNum * asz.width(),
00275         2 * Margin + asz.height()
00276     );
00277 
00278     if ( d_data->arrowType == Qt::UpArrow || d_data->arrowType == Qt::DownArrow )
00279         sz.transpose();
00280 
00281     QStyleOption styleOption;
00282     styleOption.init( this );
00283 
00284     sz = style()->sizeFromContents( QStyle::CT_PushButton,
00285         &styleOption, sz, this );
00286 
00287     return sz;
00288 }
00289 
00297 QSize QwtArrowButton::arrowSize( Qt::ArrowType arrowType,
00298     const QSize &boundingSize ) const
00299 {
00300     QSize bs = boundingSize;
00301     if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow )
00302         bs.transpose();
00303 
00304     const int MinLen = 2;
00305     const QSize sz = bs.expandedTo(
00306         QSize( MinLen, 2 * MinLen - 1 ) ); // minimum
00307 
00308     int w = sz.width();
00309     int h = 2 * w - 1;
00310 
00311     if ( h > sz.height() )
00312     {
00313         h = sz.height();
00314         w = ( h + 1 ) / 2;
00315     }
00316 
00317     QSize arrSize( w, h );
00318     if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow )
00319         arrSize.transpose();
00320 
00321     return arrSize;
00322 }
00323 
00327 void QwtArrowButton::keyPressEvent( QKeyEvent *event )
00328 {
00329     if ( event->isAutoRepeat() && event->key() == Qt::Key_Space )
00330         Q_EMIT clicked();
00331 
00332     QPushButton::keyPressEvent( event );
00333 }


plotjuggler
Author(s): Davide Faconti
autogenerated on Fri Sep 1 2017 02:41:56