You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
359 lines
0 B
359 lines
0 B
15 years ago
|
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
|
||
|
* Qwt Widget Library
|
||
|
* Copyright (C) 1997 Josef Wilgen
|
||
|
* Copyright (C) 2002 Uwe Rathmann
|
||
14 years ago
|
*
|
||
15 years ago
|
* This library is free software; you can redistribute it and/or
|
||
|
* modify it under the terms of the Qwt License, Version 1.0
|
||
|
*****************************************************************************/
|
||
|
|
||
|
#include <qpainter.h>
|
||
|
#include <qstyle.h>
|
||
|
#include <qevent.h>
|
||
|
#include "qwt_math.h"
|
||
|
#include "qwt_polygon.h"
|
||
|
#include "qwt_arrow_button.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;
|
||
|
};
|
||
|
|
||
|
|
||
|
#if QT_VERSION >= 0x040000
|
||
|
#include <qstyleoption.h>
|
||
|
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;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/*!
|
||
|
\param num Number of arrows
|
||
|
\param arrowType see Qt::ArowType in the Qt docs.
|
||
|
\param parent Parent widget
|
||
|
*/
|
||
14 years ago
|
QwtArrowButton::QwtArrowButton(int num,
|
||
|
Qt::ArrowType arrowType, QWidget *parent):
|
||
15 years ago
|
QPushButton(parent)
|
||
|
{
|
||
|
d_data = new PrivateData;
|
||
|
d_data->num = qwtLim(num, 1, MaxNum);
|
||
|
d_data->arrowType = arrowType;
|
||
|
|
||
|
setAutoRepeat(true);
|
||
|
setAutoDefault(false);
|
||
|
|
||
14 years ago
|
switch(d_data->arrowType) {
|
||
|
case Qt::LeftArrow:
|
||
|
case Qt::RightArrow:
|
||
|
setSizePolicy(QSizePolicy::Expanding,
|
||
|
QSizePolicy::Fixed);
|
||
|
break;
|
||
|
default:
|
||
|
setSizePolicy(QSizePolicy::Fixed,
|
||
|
QSizePolicy::Expanding);
|
||
15 years ago
|
}
|
||
|
}
|
||
|
|
||
|
//! Destructor
|
||
|
QwtArrowButton::~QwtArrowButton()
|
||
|
{
|
||
|
delete d_data;
|
||
|
d_data = NULL;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\brief The direction of the arrows
|
||
|
*/
|
||
14 years ago
|
Qt::ArrowType QwtArrowButton::arrowType() const
|
||
|
{
|
||
|
return d_data->arrowType;
|
||
15 years ago
|
}
|
||
|
|
||
|
/*!
|
||
|
\brief The number of arrows
|
||
|
*/
|
||
14 years ago
|
int QwtArrowButton::num() const
|
||
|
{
|
||
|
return d_data->num;
|
||
15 years ago
|
}
|
||
|
|
||
|
/*!
|
||
|
\return the bounding rect for the label
|
||
|
*/
|
||
|
QRect QwtArrowButton::labelRect() const
|
||
|
{
|
||
|
const int m = Margin;
|
||
|
|
||
|
QRect r = rect();
|
||
14 years ago
|
r.setRect(r.x() + m, r.y() + m,
|
||
|
r.width() - 2 * m, r.height() - 2 * m);
|
||
15 years ago
|
|
||
14 years ago
|
if ( isDown() ) {
|
||
15 years ago
|
int ph, pv;
|
||
|
#if QT_VERSION < 0x040000
|
||
|
ph = style().pixelMetric(
|
||
14 years ago
|
QStyle::PM_ButtonShiftHorizontal, this);
|
||
15 years ago
|
pv = style().pixelMetric(
|
||
14 years ago
|
QStyle::PM_ButtonShiftVertical, this);
|
||
15 years ago
|
r.moveBy(ph, pv);
|
||
|
#else
|
||
|
QStyleOptionButton option = styleOpt(this);
|
||
|
ph = style()->pixelMetric(
|
||
14 years ago
|
QStyle::PM_ButtonShiftHorizontal, &option, this);
|
||
15 years ago
|
pv = style()->pixelMetric(
|
||
14 years ago
|
QStyle::PM_ButtonShiftVertical, &option, this);
|
||
15 years ago
|
r.translate(ph, pv);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
#if QT_VERSION >= 0x040000
|
||
|
/*!
|
||
|
Paint event handler
|
||
|
\param event Paint event
|
||
|
*/
|
||
|
void QwtArrowButton::paintEvent(QPaintEvent *event)
|
||
|
{
|
||
|
QPushButton::paintEvent(event);
|
||
|
QPainter painter(this);
|
||
|
drawButtonLabel(&painter);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/*!
|
||
|
\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 ||
|
||
14 years ago
|
d_data->arrowType == Qt::DownArrow;
|
||
15 years ago
|
|
||
|
const QRect r = labelRect();
|
||
|
QSize boundingSize = labelRect().size();
|
||
|
if ( isVertical )
|
||
|
boundingSize.transpose();
|
||
14 years ago
|
|
||
|
const int w =
|
||
15 years ago
|
(boundingSize.width() - (MaxNum - 1) * Spacing) / MaxNum;
|
||
|
|
||
14 years ago
|
QSize arrow = arrowSize(Qt::RightArrow,
|
||
|
QSize(w, boundingSize.height()));
|
||
15 years ago
|
|
||
|
if ( isVertical )
|
||
|
arrow.transpose();
|
||
|
|
||
|
QRect contentsSize; // aligned rect where to paint all arrows
|
||
14 years ago
|
if ( d_data->arrowType == Qt::LeftArrow || d_data->arrowType == Qt::RightArrow ) {
|
||
|
contentsSize.setWidth(d_data->num * arrow.width()
|
||
|
+ (d_data->num - 1) * Spacing);
|
||
15 years ago
|
contentsSize.setHeight(arrow.height());
|
||
14 years ago
|
} else {
|
||
15 years ago
|
contentsSize.setWidth(arrow.width());
|
||
14 years ago
|
contentsSize.setHeight(d_data->num * arrow.height()
|
||
|
+ (d_data->num - 1) * Spacing);
|
||
15 years ago
|
}
|
||
|
|
||
|
QRect arrowRect(contentsSize);
|
||
|
arrowRect.moveCenter(r.center());
|
||
|
arrowRect.setSize(arrow);
|
||
|
|
||
|
painter->save();
|
||
14 years ago
|
for (int i = 0; i < d_data->num; i++) {
|
||
15 years ago
|
drawArrow(painter, arrowRect, d_data->arrowType);
|
||
|
|
||
|
int dx = 0;
|
||
|
int dy = 0;
|
||
|
|
||
|
if ( isVertical )
|
||
|
dy = arrow.height() + Spacing;
|
||
|
else
|
||
|
dx = arrow.width() + Spacing;
|
||
|
|
||
|
#if QT_VERSION >= 0x040000
|
||
|
arrowRect.translate(dx, dy);
|
||
|
#else
|
||
|
arrowRect.moveBy(dx, dy);
|
||
|
#endif
|
||
|
}
|
||
|
painter->restore();
|
||
|
|
||
14 years ago
|
if ( hasFocus() ) {
|
||
15 years ago
|
#if QT_VERSION >= 0x040000
|
||
|
QStyleOptionFocusRect option;
|
||
|
option.init(this);
|
||
|
option.backgroundColor = palette().color(QPalette::Background);
|
||
|
|
||
14 years ago
|
style()->drawPrimitive(QStyle::PE_FrameFocusRect,
|
||
|
&option, painter, this);
|
||
15 years ago
|
#else
|
||
14 years ago
|
const QRect focusRect =
|
||
15 years ago
|
style().subRect(QStyle::SR_PushButtonFocusRect, this);
|
||
|
style().drawPrimitive(QStyle::PE_FocusRect, painter,
|
||
14 years ago
|
focusRect, colorGroup());
|
||
15 years ago
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
Draw an arrow int a bounding rect
|
||
|
|
||
|
\param painter Painter
|
||
|
\param r Rectangle where to paint the arrow
|
||
|
\param arrowType Arrow type
|
||
|
*/
|
||
14 years ago
|
void QwtArrowButton::drawArrow(QPainter *painter,
|
||
|
const QRect &r, Qt::ArrowType arrowType) const
|
||
15 years ago
|
{
|
||
|
QwtPolygon pa(3);
|
||
|
|
||
14 years ago
|
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;
|
||
15 years ago
|
}
|
||
|
|
||
|
painter->save();
|
||
|
#if QT_VERSION < 0x040000
|
||
|
painter->setPen(colorGroup().buttonText());
|
||
|
painter->setBrush(colorGroup().brush(QColorGroup::ButtonText));
|
||
|
#else
|
||
|
painter->setPen(palette().color(QPalette::ButtonText));
|
||
|
painter->setBrush(palette().brush(QPalette::ButtonText));
|
||
|
#endif
|
||
|
painter->drawPolygon(pa);
|
||
|
painter->restore();
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\return a size hint
|
||
|
*/
|
||
|
QSize QwtArrowButton::sizeHint() const
|
||
|
{
|
||
|
return minimumSizeHint();
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
\brief Return a minimum size hint
|
||
|
*/
|
||
|
QSize QwtArrowButton::minimumSizeHint() const
|
||
|
{
|
||
14 years ago
|
const QSize asz = arrowSize(Qt::RightArrow, QSize());
|
||
15 years ago
|
|
||
|
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();
|
||
|
|
||
|
#if QT_VERSION >= 0x040000
|
||
|
QStyleOption styleOption;
|
||
|
styleOption.init(this);
|
||
|
|
||
14 years ago
|
const QSize hsz = style()->sizeFromContents(QStyle::CT_PushButton,
|
||
|
&styleOption, sz, this);
|
||
15 years ago
|
#if QT_VERSION < 0x040300
|
||
|
if ( hsz.width() != 80 ) // avoid a bug in the Cleanlooks style
|
||
|
#endif
|
||
|
sz = hsz;
|
||
|
|
||
|
#else
|
||
|
sz = style().sizeFromContents(QStyle::CT_PushButton, this, sz);
|
||
|
#endif
|
||
|
|
||
|
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,
|
||
14 years ago
|
const QSize &boundingSize) const
|
||
15 years ago
|
{
|
||
|
QSize bs = boundingSize;
|
||
|
if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow )
|
||
|
bs.transpose();
|
||
14 years ago
|
|
||
15 years ago
|
const int MinLen = 2;
|
||
|
const QSize sz = bs.expandedTo(
|
||
14 years ago
|
QSize(MinLen, 2 * MinLen - 1)); // minimum
|
||
15 years ago
|
|
||
|
int w = sz.width();
|
||
|
int h = 2 * w - 1;
|
||
|
|
||
14 years ago
|
if ( h > sz.height() ) {
|
||
15 years ago
|
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 *e)
|
||
|
{
|
||
|
if ( e->isAutoRepeat() && e->key() == Qt::Key_Space )
|
||
|
emit clicked();
|
||
|
|
||
|
QPushButton::keyPressEvent(e);
|
||
|
}
|