Qwt User's Guide 6.3.0
Loading...
Searching...
No Matches
qwt_arrow_button.cpp
1/******************************************************************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2002 Uwe Rathmann
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the Qwt License, Version 1.0
8 *****************************************************************************/
9
10#include "qwt_arrow_button.h"
11#include "qwt.h"
12
13#include <qpainter.h>
14#include <qstyle.h>
15#include <qstyleoption.h>
16#include <qevent.h>
17
18static const int MaxNum = 3;
19static const int Margin = 2;
20static const int Spacing = 1;
21
22class QwtArrowButton::PrivateData
23{
24 public:
25 int num;
26 Qt::ArrowType arrowType;
27};
28
29static QStyleOptionButton styleOpt( const QwtArrowButton* btn )
30{
31 QStyleOptionButton option;
32 option.initFrom( btn );
33 option.features = QStyleOptionButton::None;
34 if ( btn->isFlat() )
35 option.features |= QStyleOptionButton::Flat;
36 if ( btn->menu() )
37 option.features |= QStyleOptionButton::HasMenu;
38 if ( btn->autoDefault() || btn->isDefault() )
39 option.features |= QStyleOptionButton::AutoDefaultButton;
40 if ( btn->isDefault() )
41 option.features |= QStyleOptionButton::DefaultButton;
42 if ( btn->isDown() )
43 option.state |= QStyle::State_Sunken;
44 if ( !btn->isFlat() && !btn->isDown() )
45 option.state |= QStyle::State_Raised;
46
47 return option;
48}
49
55QwtArrowButton::QwtArrowButton( int num, Qt::ArrowType arrowType, QWidget* parent )
56 : QPushButton( parent )
57{
58 m_data = new PrivateData;
59 m_data->num = qBound( 1, num, MaxNum );
60 m_data->arrowType = arrowType;
61
62 setAutoRepeat( true );
63 setAutoDefault( false );
64
65 switch ( m_data->arrowType )
66 {
67 case Qt::LeftArrow:
68 case Qt::RightArrow:
69 setSizePolicy( QSizePolicy::Expanding,
70 QSizePolicy::Fixed );
71 break;
72 default:
73 setSizePolicy( QSizePolicy::Fixed,
74 QSizePolicy::Expanding );
75 }
76}
77
80{
81 delete m_data;
82 m_data = NULL;
83}
84
88Qt::ArrowType QwtArrowButton::arrowType() const
89{
90 return m_data->arrowType;
91}
92
97{
98 return m_data->num;
99}
100
105{
106 const int m = Margin;
107
108 QRect r = rect();
109 r.setRect( r.x() + m, r.y() + m,
110 r.width() - 2 * m, r.height() - 2 * m );
111
112 if ( isDown() )
113 {
114 QStyleOptionButton option = styleOpt( this );
115 const int ph = style()->pixelMetric(
116 QStyle::PM_ButtonShiftHorizontal, &option, this );
117 const int pv = style()->pixelMetric(
118 QStyle::PM_ButtonShiftVertical, &option, this );
119
120 r.translate( ph, pv );
121 }
122
123 return r;
124}
125
130void QwtArrowButton::paintEvent( QPaintEvent* event )
131{
132 QPushButton::paintEvent( event );
133 QPainter painter( this );
134 drawButtonLabel( &painter );
135}
136
143void QwtArrowButton::drawButtonLabel( QPainter* painter )
144{
145 const bool isVertical = m_data->arrowType == Qt::UpArrow ||
146 m_data->arrowType == Qt::DownArrow;
147
148 const QRect r = labelRect();
149 QSize boundingSize = labelRect().size();
150 if ( isVertical )
151 boundingSize.transpose();
152
153 const int w =
154 ( boundingSize.width() - ( MaxNum - 1 ) * Spacing ) / MaxNum;
155
156 QSize arrow = arrowSize( Qt::RightArrow,
157 QSize( w, boundingSize.height() ) );
158
159 if ( isVertical )
160 arrow.transpose();
161
162 QRect contentsSize; // aligned rect where to paint all arrows
163 if ( m_data->arrowType == Qt::LeftArrow || m_data->arrowType == Qt::RightArrow )
164 {
165 contentsSize.setWidth( m_data->num * arrow.width()
166 + ( m_data->num - 1 ) * Spacing );
167 contentsSize.setHeight( arrow.height() );
168 }
169 else
170 {
171 contentsSize.setWidth( arrow.width() );
172 contentsSize.setHeight( m_data->num * arrow.height()
173 + ( m_data->num - 1 ) * Spacing );
174 }
175
176 QRect arrowRect( contentsSize );
177 arrowRect.moveCenter( r.center() );
178 arrowRect.setSize( arrow );
179
180 painter->save();
181 for ( int i = 0; i < m_data->num; i++ )
182 {
183 drawArrow( painter, arrowRect, m_data->arrowType );
184
185 int dx = 0;
186 int dy = 0;
187
188 if ( isVertical )
189 dy = arrow.height() + Spacing;
190 else
191 dx = arrow.width() + Spacing;
192
193 arrowRect.translate( dx, dy );
194 }
195 painter->restore();
196
197 if ( hasFocus() )
198 {
199 QStyleOptionFocusRect option;
200 option.initFrom( this );
201 option.backgroundColor = palette().color( QPalette::Window );
202
203 style()->drawPrimitive( QStyle::PE_FrameFocusRect,
204 &option, painter, this );
205 }
206}
207
215void QwtArrowButton::drawArrow( QPainter* painter,
216 const QRect& r, Qt::ArrowType arrowType ) const
217{
218 QPolygon pa( 3 );
219
220 switch ( arrowType )
221 {
222 case Qt::UpArrow:
223 pa.setPoint( 0, r.bottomLeft() );
224 pa.setPoint( 1, r.bottomRight() );
225 pa.setPoint( 2, r.center().x(), r.top() );
226 break;
227 case Qt::DownArrow:
228 pa.setPoint( 0, r.topLeft() );
229 pa.setPoint( 1, r.topRight() );
230 pa.setPoint( 2, r.center().x(), r.bottom() );
231 break;
232 case Qt::RightArrow:
233 pa.setPoint( 0, r.topLeft() );
234 pa.setPoint( 1, r.bottomLeft() );
235 pa.setPoint( 2, r.right(), r.center().y() );
236 break;
237 case Qt::LeftArrow:
238 pa.setPoint( 0, r.topRight() );
239 pa.setPoint( 1, r.bottomRight() );
240 pa.setPoint( 2, r.left(), r.center().y() );
241 break;
242 default:
243 break;
244 }
245
246 painter->save();
247
248 painter->setRenderHint( QPainter::Antialiasing, true );
249 painter->setPen( Qt::NoPen );
250 painter->setBrush( palette().brush( QPalette::ButtonText ) );
251 painter->drawPolygon( pa );
252
253 painter->restore();
254}
255
260{
261 const QSize hint = minimumSizeHint();
262 return qwtExpandedToGlobalStrut( hint );
263}
264
269{
270 const QSize asz = arrowSize( Qt::RightArrow, QSize() );
271
272 QSize sz(
273 2 * Margin + ( MaxNum - 1 ) * Spacing + MaxNum * asz.width(),
274 2 * Margin + asz.height()
275 );
276
277 if ( m_data->arrowType == Qt::UpArrow || m_data->arrowType == Qt::DownArrow )
278 sz.transpose();
279
280 QStyleOption styleOption;
281 styleOption.initFrom( this );
282
283 sz = style()->sizeFromContents( QStyle::CT_PushButton,
284 &styleOption, sz, this );
285
286 return sz;
287}
288
296QSize QwtArrowButton::arrowSize( Qt::ArrowType arrowType,
297 const QSize& boundingSize ) const
298{
299 QSize bs = boundingSize;
300 if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow )
301 bs.transpose();
302
303 const int MinLen = 2;
304 const QSize sz = bs.expandedTo(
305 QSize( MinLen, 2 * MinLen - 1 ) ); // minimum
306
307 int w = sz.width();
308 int h = 2 * w - 1;
309
310 if ( h > sz.height() )
311 {
312 h = sz.height();
313 w = ( h + 1 ) / 2;
314 }
315
316 QSize arrSize( w, h );
317 if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow )
318 arrSize.transpose();
319
320 return arrSize;
321}
322
326void QwtArrowButton::keyPressEvent( QKeyEvent* event )
327{
328 if ( event->isAutoRepeat() && event->key() == Qt::Key_Space )
329 Q_EMIT clicked();
330
331 QPushButton::keyPressEvent( event );
332}
Arrow Button.
virtual QSize arrowSize(Qt::ArrowType, const QSize &boundingSize) const
virtual void keyPressEvent(QKeyEvent *) override
autoRepeat for the space keys
virtual ~QwtArrowButton()
Destructor.
virtual void drawArrow(QPainter *, const QRect &, Qt::ArrowType) const
virtual QRect labelRect() const
virtual void paintEvent(QPaintEvent *) override
int num() const
The number of arrows.
Qt::ArrowType arrowType() const
The direction of the arrows.
QwtArrowButton(int num, Qt::ArrowType, QWidget *parent=NULL)
virtual QSize minimumSizeHint() const override
Return a minimum size hint.
virtual QSize sizeHint() const override
virtual void drawButtonLabel(QPainter *)
Draw the button label.