qwt_arrow_button.cpp
Go to the documentation of this file.
1 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
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 
18 static const int MaxNum = 3;
19 static const int Margin = 2;
20 static const int Spacing = 1;
21 
23 {
24 public:
25  int num;
26  Qt::ArrowType arrowType;
27 };
28 
29 static 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 
56  Qt::ArrowType arrowType, QWidget *parent ):
57  QPushButton( parent )
58 {
59  d_data = new PrivateData;
60  d_data->num = qBound( 1, num, MaxNum );
62 
63  setAutoRepeat( true );
64  setAutoDefault( false );
65 
66  switch ( d_data->arrowType )
67  {
68  case Qt::LeftArrow:
69  case Qt::RightArrow:
70  setSizePolicy( QSizePolicy::Expanding,
71  QSizePolicy::Fixed );
72  break;
73  default:
74  setSizePolicy( QSizePolicy::Fixed,
75  QSizePolicy::Expanding );
76  }
77 }
78 
81 {
82  delete d_data;
83  d_data = NULL;
84 }
85 
89 Qt::ArrowType QwtArrowButton::arrowType() const
90 {
91  return d_data->arrowType;
92 }
93 
98 {
99  return d_data->num;
100 }
101 
106 {
107  const int m = Margin;
108 
109  QRect r = rect();
110  r.setRect( r.x() + m, r.y() + m,
111  r.width() - 2 * m, r.height() - 2 * m );
112 
113  if ( isDown() )
114  {
115  QStyleOptionButton option = styleOpt( this );
116  const int ph = style()->pixelMetric(
117  QStyle::PM_ButtonShiftHorizontal, &option, this );
118  const int pv = style()->pixelMetric(
119  QStyle::PM_ButtonShiftVertical, &option, this );
120 
121  r.translate( ph, pv );
122  }
123 
124  return r;
125 }
126 
131 void QwtArrowButton::paintEvent( QPaintEvent *event )
132 {
133  QPushButton::paintEvent( event );
134  QPainter painter( this );
135  drawButtonLabel( &painter );
136 }
137 
144 void QwtArrowButton::drawButtonLabel( QPainter *painter )
145 {
146  const bool isVertical = d_data->arrowType == Qt::UpArrow ||
147  d_data->arrowType == Qt::DownArrow;
148 
149  const QRect r = labelRect();
150  QSize boundingSize = labelRect().size();
151  if ( isVertical )
152  boundingSize.transpose();
153 
154  const int w =
155  ( boundingSize.width() - ( MaxNum - 1 ) * Spacing ) / MaxNum;
156 
157  QSize arrow = arrowSize( Qt::RightArrow,
158  QSize( w, boundingSize.height() ) );
159 
160  if ( isVertical )
161  arrow.transpose();
162 
163  QRect contentsSize; // aligned rect where to paint all arrows
164  if ( d_data->arrowType == Qt::LeftArrow || d_data->arrowType == Qt::RightArrow )
165  {
166  contentsSize.setWidth( d_data->num * arrow.width()
167  + ( d_data->num - 1 ) * Spacing );
168  contentsSize.setHeight( arrow.height() );
169  }
170  else
171  {
172  contentsSize.setWidth( arrow.width() );
173  contentsSize.setHeight( d_data->num * arrow.height()
174  + ( d_data->num - 1 ) * Spacing );
175  }
176 
177  QRect arrowRect( contentsSize );
178  arrowRect.moveCenter( r.center() );
179  arrowRect.setSize( arrow );
180 
181  painter->save();
182  for ( int i = 0; i < d_data->num; i++ )
183  {
184  drawArrow( painter, arrowRect, d_data->arrowType );
185 
186  int dx = 0;
187  int dy = 0;
188 
189  if ( isVertical )
190  dy = arrow.height() + Spacing;
191  else
192  dx = arrow.width() + Spacing;
193 
194  arrowRect.translate( dx, dy );
195  }
196  painter->restore();
197 
198  if ( hasFocus() )
199  {
200  QStyleOptionFocusRect option;
201  option.initFrom( this );
202  option.backgroundColor = palette().color( QPalette::Window );
203 
204  style()->drawPrimitive( QStyle::PE_FrameFocusRect,
205  &option, painter, this );
206  }
207 }
208 
216 void QwtArrowButton::drawArrow( QPainter *painter,
217  const QRect &r, Qt::ArrowType arrowType ) const
218 {
219  QPolygon pa( 3 );
220 
221  switch ( arrowType )
222  {
223  case Qt::UpArrow:
224  pa.setPoint( 0, r.bottomLeft() );
225  pa.setPoint( 1, r.bottomRight() );
226  pa.setPoint( 2, r.center().x(), r.top() );
227  break;
228  case Qt::DownArrow:
229  pa.setPoint( 0, r.topLeft() );
230  pa.setPoint( 1, r.topRight() );
231  pa.setPoint( 2, r.center().x(), r.bottom() );
232  break;
233  case Qt::RightArrow:
234  pa.setPoint( 0, r.topLeft() );
235  pa.setPoint( 1, r.bottomLeft() );
236  pa.setPoint( 2, r.right(), r.center().y() );
237  break;
238  case Qt::LeftArrow:
239  pa.setPoint( 0, r.topRight() );
240  pa.setPoint( 1, r.bottomRight() );
241  pa.setPoint( 2, r.left(), r.center().y() );
242  break;
243  default:
244  break;
245  }
246 
247  painter->save();
248 
249  painter->setRenderHint( QPainter::Antialiasing, true );
250  painter->setPen( Qt::NoPen );
251  painter->setBrush( palette().brush( QPalette::ButtonText ) );
252  painter->drawPolygon( pa );
253 
254  painter->restore();
255 }
256 
261 {
262  const QSize hint = minimumSizeHint();
263  return qwtExpandedToGlobalStrut( hint );
264 }
265 
270 {
271  const QSize asz = arrowSize( Qt::RightArrow, QSize() );
272 
273  QSize sz(
274  2 * Margin + ( MaxNum - 1 ) * Spacing + MaxNum * asz.width(),
275  2 * Margin + asz.height()
276  );
277 
278  if ( d_data->arrowType == Qt::UpArrow || d_data->arrowType == Qt::DownArrow )
279  sz.transpose();
280 
281  QStyleOption styleOption;
282  styleOption.initFrom( this );
283 
284  sz = style()->sizeFromContents( QStyle::CT_PushButton,
285  &styleOption, sz, this );
286 
287  return sz;
288 }
289 
298  const QSize &boundingSize ) const
299 {
300  QSize bs = boundingSize;
301  if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow )
302  bs.transpose();
303 
304  const int MinLen = 2;
305  const QSize sz = bs.expandedTo(
306  QSize( MinLen, 2 * MinLen - 1 ) ); // minimum
307 
308  int w = sz.width();
309  int h = 2 * w - 1;
310 
311  if ( h > sz.height() )
312  {
313  h = sz.height();
314  w = ( h + 1 ) / 2;
315  }
316 
317  QSize arrSize( w, h );
318  if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow )
319  arrSize.transpose();
320 
321  return arrSize;
322 }
323 
327 void QwtArrowButton::keyPressEvent( QKeyEvent *event )
328 {
329  if ( event->isAutoRepeat() && event->key() == Qt::Key_Space )
330  Q_EMIT clicked();
331 
332  QPushButton::keyPressEvent( event );
333 }
virtual void drawArrow(QPainter *, const QRect &, Qt::ArrowType) const
static const int MaxNum
QSize qwtExpandedToGlobalStrut(const QSize &size)
Definition: qwt.cpp:21
virtual void drawButtonLabel(QPainter *)
Draw the button label.
PrivateData * d_data
QwtArrowButton(int num, Qt::ArrowType, QWidget *parent=NULL)
Arrow Button.
Qt::ArrowType arrowType() const
The direction of the arrows.
virtual QSize minimumSizeHint() const QWT_OVERRIDE
Return a minimum size hint.
static const int Margin
int num() const
The number of arrows.
virtual QSize arrowSize(Qt::ArrowType, const QSize &boundingSize) const
virtual void paintEvent(QPaintEvent *) QWT_OVERRIDE
static const int Spacing
static QStyleOptionButton styleOpt(const QwtArrowButton *btn)
virtual QSize sizeHint() const QWT_OVERRIDE
virtual void keyPressEvent(QKeyEvent *) QWT_OVERRIDE
autoRepeat for the space keys
virtual ~QwtArrowButton()
Destructor.
virtual QRect labelRect() const


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 03:48:10