qwt_arrow_button.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 #include <qpainter.h>
00011 #include <qstyle.h>
00012 #include <qevent.h>
00013 #include "qwt_math.h"
00014 #include "qwt_polygon.h"
00015 #include "qwt_arrow_button.h"
00016 
00017 static const int MaxNum = 3;
00018 static const int Margin = 2;
00019 static const int Spacing = 1;
00020 
00021 class QwtArrowButton::PrivateData
00022 {
00023 public:
00024     int num;
00025     Qt::ArrowType arrowType;
00026 };
00027 
00028 
00029 #if QT_VERSION >= 0x040000
00030 #include <qstyleoption.h>
00031 static QStyleOptionButton styleOpt(const QwtArrowButton* btn)
00032 {
00033     QStyleOptionButton option;
00034     option.init(btn);
00035     option.features = QStyleOptionButton::None;
00036     if (btn->isFlat())
00037         option.features |= QStyleOptionButton::Flat;
00038     if (btn->menu())
00039         option.features |= QStyleOptionButton::HasMenu;
00040     if (btn->autoDefault() || btn->isDefault())
00041         option.features |= QStyleOptionButton::AutoDefaultButton;
00042     if (btn->isDefault())
00043         option.features |= QStyleOptionButton::DefaultButton;
00044     if (btn->isDown())
00045         option.state |= QStyle::State_Sunken;
00046     if (!btn->isFlat() && !btn->isDown())
00047         option.state |= QStyle::State_Raised;
00048 
00049     return option;
00050 }
00051 #endif
00052 
00058 QwtArrowButton::QwtArrowButton(int num, 
00059         Qt::ArrowType arrowType, QWidget *parent): 
00060     QPushButton(parent)
00061 {
00062     d_data = new PrivateData;
00063     d_data->num = qwtLim(num, 1, MaxNum);
00064     d_data->arrowType = arrowType;
00065 
00066     setAutoRepeat(true);
00067     setAutoDefault(false);
00068 
00069     switch(d_data->arrowType)
00070     {
00071         case Qt::LeftArrow:
00072         case Qt::RightArrow:
00073             setSizePolicy(QSizePolicy::Expanding, 
00074                 QSizePolicy::Fixed);
00075             break;
00076         default:
00077             setSizePolicy(QSizePolicy::Fixed, 
00078                 QSizePolicy::Expanding);
00079     }
00080 }
00081 
00083 QwtArrowButton::~QwtArrowButton()
00084 {
00085     delete d_data;
00086     d_data = NULL;
00087 }
00088 
00092 Qt::ArrowType QwtArrowButton::arrowType() const 
00093 { 
00094     return d_data->arrowType; 
00095 }
00096 
00100 int QwtArrowButton::num() const 
00101 { 
00102     return d_data->num; 
00103 }
00104 
00108 QRect QwtArrowButton::labelRect() const
00109 {
00110     const int m = Margin;
00111 
00112     QRect r = rect();
00113     r.setRect(r.x() + m, r.y() + m, 
00114         r.width() - 2 * m, r.height() - 2 * m);
00115 
00116     if ( isDown() )
00117     {
00118         int ph, pv;
00119 #if QT_VERSION < 0x040000
00120         ph = style().pixelMetric(
00121             QStyle::PM_ButtonShiftHorizontal, this);
00122         pv = style().pixelMetric(
00123             QStyle::PM_ButtonShiftVertical, this);
00124         r.moveBy(ph, pv);
00125 #else
00126         QStyleOptionButton option = styleOpt(this);
00127         ph = style()->pixelMetric(
00128             QStyle::PM_ButtonShiftHorizontal, &option, this);
00129         pv = style()->pixelMetric(
00130             QStyle::PM_ButtonShiftVertical, &option, this);
00131         r.translate(ph, pv);
00132 #endif
00133     }
00134 
00135     return r;
00136 }
00137 
00138 #if QT_VERSION >= 0x040000
00139 
00143 void QwtArrowButton::paintEvent(QPaintEvent *event)
00144 {
00145     QPushButton::paintEvent(event);
00146     QPainter painter(this);
00147     drawButtonLabel(&painter);
00148 }
00149 #endif
00150 
00157 void QwtArrowButton::drawButtonLabel(QPainter *painter)
00158 {
00159     const bool isVertical = d_data->arrowType == Qt::UpArrow ||
00160         d_data->arrowType == Qt::DownArrow;
00161 
00162     const QRect r = labelRect();
00163     QSize boundingSize = labelRect().size();
00164     if ( isVertical )
00165         boundingSize.transpose();
00166         
00167     const int w = 
00168         (boundingSize.width() - (MaxNum - 1) * Spacing) / MaxNum;
00169 
00170     QSize arrow = arrowSize(Qt::RightArrow, 
00171         QSize(w, boundingSize.height()));
00172 
00173     if ( isVertical )
00174         arrow.transpose();
00175 
00176     QRect contentsSize; // aligned rect where to paint all arrows
00177     if ( d_data->arrowType == Qt::LeftArrow || d_data->arrowType == Qt::RightArrow )
00178     {
00179         contentsSize.setWidth(d_data->num * arrow.width() 
00180             + (d_data->num - 1) * Spacing);
00181         contentsSize.setHeight(arrow.height());
00182     }
00183     else
00184     {
00185         contentsSize.setWidth(arrow.width());
00186         contentsSize.setHeight(d_data->num * arrow.height() 
00187             + (d_data->num - 1) * Spacing);
00188     }
00189 
00190     QRect arrowRect(contentsSize);
00191     arrowRect.moveCenter(r.center());
00192     arrowRect.setSize(arrow);
00193 
00194     painter->save();
00195     for (int i = 0; i < d_data->num; i++)
00196     {
00197         drawArrow(painter, arrowRect, d_data->arrowType);
00198 
00199         int dx = 0;
00200         int dy = 0;
00201 
00202         if ( isVertical )
00203             dy = arrow.height() + Spacing;
00204         else
00205             dx = arrow.width() + Spacing;
00206 
00207 #if QT_VERSION >= 0x040000
00208         arrowRect.translate(dx, dy);
00209 #else
00210         arrowRect.moveBy(dx, dy);
00211 #endif
00212     }
00213     painter->restore();
00214 
00215     if ( hasFocus() )
00216     {
00217 #if QT_VERSION >= 0x040000
00218         QStyleOptionFocusRect option;
00219         option.init(this);
00220         option.backgroundColor = palette().color(QPalette::Background);
00221 
00222         style()->drawPrimitive(QStyle::PE_FrameFocusRect, 
00223             &option, painter, this);
00224 #else
00225         const QRect focusRect =  
00226             style().subRect(QStyle::SR_PushButtonFocusRect, this);
00227         style().drawPrimitive(QStyle::PE_FocusRect, painter,
00228             focusRect, colorGroup());
00229 #endif
00230     }
00231 }
00232 
00240 void QwtArrowButton::drawArrow(QPainter *painter, 
00241     const QRect &r, Qt::ArrowType arrowType) const 
00242 {
00243     QwtPolygon pa(3);
00244 
00245     switch(arrowType)
00246     {
00247         case Qt::UpArrow:
00248             pa.setPoint(0, r.bottomLeft());
00249             pa.setPoint(1, r.bottomRight());
00250             pa.setPoint(2, r.center().x(), r.top());
00251             break;
00252         case Qt::DownArrow:
00253             pa.setPoint(0, r.topLeft());
00254             pa.setPoint(1, r.topRight());
00255             pa.setPoint(2, r.center().x(), r.bottom());
00256             break;
00257         case Qt::RightArrow:
00258             pa.setPoint(0, r.topLeft());
00259             pa.setPoint(1, r.bottomLeft());
00260             pa.setPoint(2, r.right(), r.center().y());
00261             break;
00262         case Qt::LeftArrow:
00263             pa.setPoint(0, r.topRight());
00264             pa.setPoint(1, r.bottomRight());
00265             pa.setPoint(2, r.left(), r.center().y());
00266             break;
00267         default:
00268             break;
00269     }
00270 
00271     painter->save();
00272 #if QT_VERSION < 0x040000
00273     painter->setPen(colorGroup().buttonText());
00274     painter->setBrush(colorGroup().brush(QColorGroup::ButtonText));
00275 #else
00276     painter->setPen(palette().color(QPalette::ButtonText));
00277     painter->setBrush(palette().brush(QPalette::ButtonText));
00278 #endif
00279     painter->drawPolygon(pa);
00280     painter->restore();
00281 }
00282 
00286 QSize QwtArrowButton::sizeHint() const
00287 {
00288     return minimumSizeHint();
00289 }
00290 
00294 QSize QwtArrowButton::minimumSizeHint() const
00295 {
00296     const QSize asz = arrowSize(Qt::RightArrow, QSize()); 
00297 
00298     QSize sz(
00299         2 * Margin + (MaxNum - 1) * Spacing + MaxNum * asz.width(),
00300         2 * Margin + asz.height()
00301     );
00302 
00303     if ( d_data->arrowType == Qt::UpArrow || d_data->arrowType == Qt::DownArrow )
00304         sz.transpose();
00305 
00306 #if QT_VERSION >= 0x040000
00307     QStyleOption styleOption;
00308     styleOption.init(this);
00309 
00310     sz = style()->sizeFromContents(QStyle::CT_PushButton, 
00311         &styleOption, sz, this);
00312 #else
00313     sz = style().sizeFromContents(QStyle::CT_PushButton, this, sz);
00314 #endif
00315 
00316     return sz;
00317 }
00318 
00326 QSize QwtArrowButton::arrowSize(Qt::ArrowType arrowType,
00327     const QSize &boundingSize) const
00328 {
00329     QSize bs = boundingSize;
00330     if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow )
00331         bs.transpose();
00332         
00333     const int MinLen = 2;
00334     const QSize sz = bs.expandedTo(
00335         QSize(MinLen, 2 * MinLen - 1)); // minimum
00336 
00337     int w = sz.width();
00338     int h = 2 * w - 1;
00339 
00340     if ( h > sz.height() )
00341     {
00342         h = sz.height();
00343         w = (h + 1) / 2;
00344     }
00345 
00346     QSize arrSize(w, h);
00347     if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow )
00348         arrSize.transpose();
00349 
00350     return arrSize;
00351 }
00352 
00356 void QwtArrowButton::keyPressEvent(QKeyEvent *e)
00357 {
00358     if ( e->isAutoRepeat() && e->key() == Qt::Key_Space )
00359         emit clicked();
00360 
00361     QPushButton::keyPressEvent(e);
00362 }

Generated on Mon Feb 26 21:22:36 2007 for Qwt User's Guide by  doxygen 1.4.6