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