~l3on/ubuntu/oneiric/qwt/fix-921430

« back to all changes in this revision

Viewing changes to qwt-5.0.2/src/qwt_arrow_button.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Fathi Boudra
  • Date: 2007-10-05 15:20:41 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20071005152041-qmybqh4fj9jejyo2
Tags: 5.0.2-2
* Handle nostrip build option. (Closes: #437877)
* Build libqwt5-doc package in binary-indep target. (Closes: #443110)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <qpainter.h>
 
11
#include <qstyle.h>
 
12
#include <qevent.h>
 
13
#include "qwt_math.h"
 
14
#include "qwt_polygon.h"
 
15
#include "qwt_arrow_button.h"
 
16
 
 
17
static const int MaxNum = 3;
 
18
static const int Margin = 2;
 
19
static const int Spacing = 1;
 
20
 
 
21
class QwtArrowButton::PrivateData
 
22
{
 
23
public:
 
24
    int num;
 
25
    Qt::ArrowType arrowType;
 
26
};
 
27
 
 
28
 
 
29
#if QT_VERSION >= 0x040000
 
30
#include <qstyleoption.h>
 
31
static QStyleOptionButton styleOpt(const QwtArrowButton* btn)
 
32
{
 
33
    QStyleOptionButton option;
 
34
    option.init(btn);
 
35
    option.features = QStyleOptionButton::None;
 
36
    if (btn->isFlat())
 
37
        option.features |= QStyleOptionButton::Flat;
 
38
    if (btn->menu())
 
39
        option.features |= QStyleOptionButton::HasMenu;
 
40
    if (btn->autoDefault() || btn->isDefault())
 
41
        option.features |= QStyleOptionButton::AutoDefaultButton;
 
42
    if (btn->isDefault())
 
43
        option.features |= QStyleOptionButton::DefaultButton;
 
44
    if (btn->isDown())
 
45
        option.state |= QStyle::State_Sunken;
 
46
    if (!btn->isFlat() && !btn->isDown())
 
47
        option.state |= QStyle::State_Raised;
 
48
 
 
49
    return option;
 
50
}
 
51
#endif
 
52
 
 
53
/*!
 
54
  \param num Number of arrows
 
55
  \param arrowType see Qt::ArowType in the Qt docs.
 
56
  \param parent Parent widget
 
57
*/
 
58
QwtArrowButton::QwtArrowButton(int num, 
 
59
        Qt::ArrowType arrowType, QWidget *parent): 
 
60
    QPushButton(parent)
 
61
{
 
62
    d_data = new PrivateData;
 
63
    d_data->num = qwtLim(num, 1, MaxNum);
 
64
    d_data->arrowType = arrowType;
 
65
 
 
66
    setAutoRepeat(true);
 
67
    setAutoDefault(false);
 
68
 
 
69
    switch(d_data->arrowType)
 
70
    {
 
71
        case Qt::LeftArrow:
 
72
        case Qt::RightArrow:
 
73
            setSizePolicy(QSizePolicy::Expanding, 
 
74
                QSizePolicy::Fixed);
 
75
            break;
 
76
        default:
 
77
            setSizePolicy(QSizePolicy::Fixed, 
 
78
                QSizePolicy::Expanding);
 
79
    }
 
80
}
 
81
 
 
82
//! Destructor
 
83
QwtArrowButton::~QwtArrowButton()
 
84
{
 
85
    delete d_data;
 
86
    d_data = NULL;
 
87
}
 
88
 
 
89
/*!
 
90
  \brief The direction of the arrows
 
91
*/
 
92
Qt::ArrowType QwtArrowButton::arrowType() const 
 
93
 
94
    return d_data->arrowType; 
 
95
}
 
96
 
 
97
/*!
 
98
  \brief The number of arrows
 
99
*/
 
100
int QwtArrowButton::num() const 
 
101
 
102
    return d_data->num; 
 
103
}
 
104
 
 
105
/*!
 
106
  \return the bounding rect for the label
 
107
*/
 
108
QRect QwtArrowButton::labelRect() const
 
109
{
 
110
    const int m = Margin;
 
111
 
 
112
    QRect r = rect();
 
113
    r.setRect(r.x() + m, r.y() + m, 
 
114
        r.width() - 2 * m, r.height() - 2 * m);
 
115
 
 
116
    if ( isDown() )
 
117
    {
 
118
        int ph, pv;
 
119
#if QT_VERSION < 0x040000
 
120
        ph = style().pixelMetric(
 
121
            QStyle::PM_ButtonShiftHorizontal, this);
 
122
        pv = style().pixelMetric(
 
123
            QStyle::PM_ButtonShiftVertical, this);
 
124
        r.moveBy(ph, pv);
 
125
#else
 
126
        QStyleOptionButton option = styleOpt(this);
 
127
        ph = style()->pixelMetric(
 
128
            QStyle::PM_ButtonShiftHorizontal, &option, this);
 
129
        pv = style()->pixelMetric(
 
130
            QStyle::PM_ButtonShiftVertical, &option, this);
 
131
        r.translate(ph, pv);
 
132
#endif
 
133
    }
 
134
 
 
135
    return r;
 
136
}
 
137
 
 
138
#if QT_VERSION >= 0x040000
 
139
/*!
 
140
   Paint event handler
 
141
   \param event Paint event
 
142
*/
 
143
void QwtArrowButton::paintEvent(QPaintEvent *event)
 
144
{
 
145
    QPushButton::paintEvent(event);
 
146
    QPainter painter(this);
 
147
    drawButtonLabel(&painter);
 
148
}
 
149
#endif
 
150
 
 
151
/*!
 
152
  \brief Draw the button label
 
153
 
 
154
  \param painter Painter
 
155
  \sa The Qt Manual on QPushButton
 
156
*/
 
157
void QwtArrowButton::drawButtonLabel(QPainter *painter)
 
158
{
 
159
    const bool isVertical = d_data->arrowType == Qt::UpArrow ||
 
160
        d_data->arrowType == Qt::DownArrow;
 
161
 
 
162
    const QRect r = labelRect();
 
163
    QSize boundingSize = labelRect().size();
 
164
    if ( isVertical )
 
165
        boundingSize.transpose();
 
166
        
 
167
    const int w = 
 
168
        (boundingSize.width() - (MaxNum - 1) * Spacing) / MaxNum;
 
169
 
 
170
    QSize arrow = arrowSize(Qt::RightArrow, 
 
171
        QSize(w, boundingSize.height()));
 
172
 
 
173
    if ( isVertical )
 
174
        arrow.transpose();
 
175
 
 
176
    QRect contentsSize; // aligned rect where to paint all arrows
 
177
    if ( d_data->arrowType == Qt::LeftArrow || d_data->arrowType == Qt::RightArrow )
 
178
    {
 
179
        contentsSize.setWidth(d_data->num * arrow.width() 
 
180
            + (d_data->num - 1) * Spacing);
 
181
        contentsSize.setHeight(arrow.height());
 
182
    }
 
183
    else
 
184
    {
 
185
        contentsSize.setWidth(arrow.width());
 
186
        contentsSize.setHeight(d_data->num * arrow.height() 
 
187
            + (d_data->num - 1) * Spacing);
 
188
    }
 
189
 
 
190
    QRect arrowRect(contentsSize);
 
191
    arrowRect.moveCenter(r.center());
 
192
    arrowRect.setSize(arrow);
 
193
 
 
194
    painter->save();
 
195
    for (int i = 0; i < d_data->num; i++)
 
196
    {
 
197
        drawArrow(painter, arrowRect, d_data->arrowType);
 
198
 
 
199
        int dx = 0;
 
200
        int dy = 0;
 
201
 
 
202
        if ( isVertical )
 
203
            dy = arrow.height() + Spacing;
 
204
        else
 
205
            dx = arrow.width() + Spacing;
 
206
 
 
207
#if QT_VERSION >= 0x040000
 
208
        arrowRect.translate(dx, dy);
 
209
#else
 
210
        arrowRect.moveBy(dx, dy);
 
211
#endif
 
212
    }
 
213
    painter->restore();
 
214
 
 
215
    if ( hasFocus() )
 
216
    {
 
217
#if QT_VERSION >= 0x040000
 
218
        QStyleOptionFocusRect option;
 
219
        option.init(this);
 
220
        option.backgroundColor = palette().color(QPalette::Background);
 
221
 
 
222
        style()->drawPrimitive(QStyle::PE_FrameFocusRect, 
 
223
            &option, painter, this);
 
224
#else
 
225
        const QRect focusRect =  
 
226
            style().subRect(QStyle::SR_PushButtonFocusRect, this);
 
227
        style().drawPrimitive(QStyle::PE_FocusRect, painter,
 
228
            focusRect, colorGroup());
 
229
#endif
 
230
    }
 
231
}
 
232
 
 
233
/*!
 
234
    Draw an arrow int a bounding rect
 
235
 
 
236
    \param painter Painter
 
237
    \param r Rectangle where to paint the arrow
 
238
    \param arrowType Arrow type
 
239
*/
 
240
void QwtArrowButton::drawArrow(QPainter *painter, 
 
241
    const QRect &r, Qt::ArrowType arrowType) const 
 
242
{
 
243
    QwtPolygon pa(3);
 
244
 
 
245
    switch(arrowType)
 
246
    {
 
247
        case Qt::UpArrow:
 
248
            pa.setPoint(0, r.bottomLeft());
 
249
            pa.setPoint(1, r.bottomRight());
 
250
            pa.setPoint(2, r.center().x(), r.top());
 
251
            break;
 
252
        case Qt::DownArrow:
 
253
            pa.setPoint(0, r.topLeft());
 
254
            pa.setPoint(1, r.topRight());
 
255
            pa.setPoint(2, r.center().x(), r.bottom());
 
256
            break;
 
257
        case Qt::RightArrow:
 
258
            pa.setPoint(0, r.topLeft());
 
259
            pa.setPoint(1, r.bottomLeft());
 
260
            pa.setPoint(2, r.right(), r.center().y());
 
261
            break;
 
262
        case Qt::LeftArrow:
 
263
            pa.setPoint(0, r.topRight());
 
264
            pa.setPoint(1, r.bottomRight());
 
265
            pa.setPoint(2, r.left(), r.center().y());
 
266
            break;
 
267
        default:
 
268
            break;
 
269
    }
 
270
 
 
271
    painter->save();
 
272
#if QT_VERSION < 0x040000
 
273
    painter->setPen(colorGroup().buttonText());
 
274
    painter->setBrush(colorGroup().brush(QColorGroup::ButtonText));
 
275
#else
 
276
    painter->setPen(palette().color(QPalette::ButtonText));
 
277
    painter->setBrush(palette().brush(QPalette::ButtonText));
 
278
#endif
 
279
    painter->drawPolygon(pa);
 
280
    painter->restore();
 
281
}
 
282
 
 
283
/*!
 
284
  \return a size hint
 
285
*/
 
286
QSize QwtArrowButton::sizeHint() const
 
287
{
 
288
    return minimumSizeHint();
 
289
}
 
290
 
 
291
/*!
 
292
  \brief Return a minimum size hint
 
293
*/
 
294
QSize QwtArrowButton::minimumSizeHint() const
 
295
{
 
296
    const QSize asz = arrowSize(Qt::RightArrow, QSize()); 
 
297
 
 
298
    QSize sz(
 
299
        2 * Margin + (MaxNum - 1) * Spacing + MaxNum * asz.width(),
 
300
        2 * Margin + asz.height()
 
301
    );
 
302
 
 
303
    if ( d_data->arrowType == Qt::UpArrow || d_data->arrowType == Qt::DownArrow )
 
304
        sz.transpose();
 
305
 
 
306
#if QT_VERSION >= 0x040000
 
307
    QStyleOption styleOption;
 
308
    styleOption.init(this);
 
309
 
 
310
    const QSize hsz = style()->sizeFromContents(QStyle::CT_PushButton, 
 
311
        &styleOption, sz, this);
 
312
#if QT_VERSION < 0x040300
 
313
    if ( hsz.width() != 80 ) // avoid a bug in the Cleanlooks style
 
314
#endif
 
315
        sz = hsz;
 
316
 
 
317
#else
 
318
    sz = style().sizeFromContents(QStyle::CT_PushButton, this, sz);
 
319
#endif
 
320
 
 
321
    return sz;
 
322
}
 
323
 
 
324
/*!
 
325
   Calculate the size for a arrow that fits into a rect of a given size
 
326
 
 
327
   \param arrowType Arrow type
 
328
   \param boundingSize Bounding size
 
329
   \return Size of the arrow
 
330
*/
 
331
QSize QwtArrowButton::arrowSize(Qt::ArrowType arrowType,
 
332
    const QSize &boundingSize) const
 
333
{
 
334
    QSize bs = boundingSize;
 
335
    if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow )
 
336
        bs.transpose();
 
337
        
 
338
    const int MinLen = 2;
 
339
    const QSize sz = bs.expandedTo(
 
340
        QSize(MinLen, 2 * MinLen - 1)); // minimum
 
341
 
 
342
    int w = sz.width();
 
343
    int h = 2 * w - 1;
 
344
 
 
345
    if ( h > sz.height() )
 
346
    {
 
347
        h = sz.height();
 
348
        w = (h + 1) / 2;
 
349
    }
 
350
 
 
351
    QSize arrSize(w, h);
 
352
    if ( arrowType == Qt::UpArrow || arrowType == Qt::DownArrow )
 
353
        arrSize.transpose();
 
354
 
 
355
    return arrSize;
 
356
}
 
357
 
 
358
/*!
 
359
  \brief autoRepeat for the space keys
 
360
*/
 
361
void QwtArrowButton::keyPressEvent(QKeyEvent *e)
 
362
{
 
363
    if ( e->isAutoRepeat() && e->key() == Qt::Key_Space )
 
364
        emit clicked();
 
365
 
 
366
    QPushButton::keyPressEvent(e);
 
367
}