00001
00002
00003
00004
00005
00006
00007
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;
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 ) );
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 }