地面站终端 App
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.

563 lines
12 KiB

/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
// vim: expandtab
#include <qpainter.h>
#include <qdrawutil.h>
#include <qstyle.h>
#include <qpen.h>
#if QT_VERSION >= 0x040000
#include <qevent.h>
#include <qstyleoption.h>
#endif
#include "qwt_math.h"
#include "qwt_painter.h"
#include "qwt_symbol.h"
#include "qwt_legend_item.h"
static const int ButtonFrame = 2;
static const int Margin = 2;
static QSize buttonShift(const QwtLegendItem *w)
{
#if QT_VERSION < 0x040000
const int ph = w->style().pixelMetric(
QStyle::PM_ButtonShiftHorizontal, w);
const int pv = w->style().pixelMetric(
QStyle::PM_ButtonShiftVertical, w);
#else
QStyleOption option;
option.init(w);
const int ph = w->style()->pixelMetric(
QStyle::PM_ButtonShiftHorizontal, &option, w);
const int pv = w->style()->pixelMetric(
QStyle::PM_ButtonShiftVertical, &option, w);
#endif
return QSize(ph, pv);
}
class QwtLegendItem::PrivateData
{
public:
PrivateData():
itemMode(QwtLegend::ReadOnlyItem),
isDown(false),
identifierWidth(8),
identifierMode(QwtLegendItem::ShowLine | QwtLegendItem::ShowText),
curvePen(Qt::NoPen),
spacing(Margin) {
symbol = new QwtSymbol();
}
~PrivateData() {
delete symbol;
}
QwtLegend::LegendItemMode itemMode;
bool isDown;
int identifierWidth;
int identifierMode;
QwtSymbol *symbol;
QPen curvePen;
int spacing;
};
/*!
\param parent Parent widget
*/
QwtLegendItem::QwtLegendItem(QWidget *parent):
QwtTextLabel(parent)
{
d_data = new PrivateData;
init(QwtText());
}
/*!
\param symbol Curve symbol
\param curvePen Curve pen
\param text Label text
\param parent Parent widget
*/
QwtLegendItem::QwtLegendItem(const QwtSymbol &symbol,
const QPen &curvePen, const QwtText &text,
QWidget *parent):
QwtTextLabel(parent)
{
d_data = new PrivateData;
delete d_data->symbol;
d_data->symbol = symbol.clone();
d_data->curvePen = curvePen;
init(text);
}
void QwtLegendItem::init(const QwtText &text)
{
setMargin(Margin);
setIndent(margin() + d_data->identifierWidth + 2 * d_data->spacing);
setText(text);
}
//! Destructor
QwtLegendItem::~QwtLegendItem()
{
delete d_data;
d_data = NULL;
}
/*!
Set the text to the legend item
\param text Text label
\sa QwtTextLabel::text()
*/
void QwtLegendItem::setText(const QwtText &text)
{
const int flags = Qt::AlignLeft | Qt::AlignVCenter
#if QT_VERSION < 0x040000
| Qt::WordBreak | Qt::ExpandTabs;
#else
| Qt::TextExpandTabs | Qt::TextWordWrap;
#endif
QwtText txt = text;
txt.setRenderFlags(flags);
QwtTextLabel::setText(txt);
}
/*!
Set the item mode
The default is QwtLegend::ReadOnlyItem
\param mode Item mode
\sa itemMode()
*/
void QwtLegendItem::setItemMode(QwtLegend::LegendItemMode mode)
{
d_data->itemMode = mode;
d_data->isDown = false;
#if QT_VERSION >= 0x040000
using namespace Qt;
#endif
setFocusPolicy(mode != QwtLegend::ReadOnlyItem ? TabFocus : NoFocus);
setMargin(ButtonFrame + Margin);
updateGeometry();
}
/*!
Return the item mode
\sa setItemMode()
*/
QwtLegend::LegendItemMode QwtLegendItem::itemMode() const
{
return d_data->itemMode;
}
/*!
Set identifier mode.
Default is ShowLine | ShowText.
\param mode Or'd values of IdentifierMode
\sa identifierMode()
*/
void QwtLegendItem::setIdentifierMode(int mode)
{
if ( mode != d_data->identifierMode ) {
d_data->identifierMode = mode;
update();
}
}
/*!
Or'd values of IdentifierMode.
\sa setIdentifierMode(), IdentifierMode
*/
int QwtLegendItem::identifierMode() const
{
return d_data->identifierMode;
}
/*!
Set the width for the identifier
Default is 8 pixels
\param width New width
\sa identifierMode(), identifierWidth
*/
void QwtLegendItem::setIdentfierWidth(int width)
{
width = qwtMax(width, 0);
if ( width != d_data->identifierWidth ) {
d_data->identifierWidth = width;
setIndent(margin() + d_data->identifierWidth
+ 2 * d_data->spacing);
}
}
/*!
Return the width of the identifier
\sa setIdentfierWidth
*/
int QwtLegendItem::identifierWidth() const
{
return d_data->identifierWidth;
}
/*!
Change the spacing
\param spacing Spacing
\sa spacing(), identifierWidth(), QwtTextLabel::margin()
*/
void QwtLegendItem::setSpacing(int spacing)
{
spacing = qwtMax(spacing, 0);
if ( spacing != d_data->spacing ) {
d_data->spacing = spacing;
setIndent(margin() + d_data->identifierWidth
+ 2 * d_data->spacing);
}
}
/*!
Return the spacing
\sa setSpacing(), identifierWidth(), QwtTextLabel::margin()
*/
int QwtLegendItem::spacing() const
{
return d_data->spacing;
}
/*!
Set curve symbol.
\param symbol Symbol
\sa symbol()
*/
void QwtLegendItem::setSymbol(const QwtSymbol &symbol)
{
delete d_data->symbol;
d_data->symbol = symbol.clone();
update();
}
/*!
\return The curve symbol.
\sa setSymbol()
*/
const QwtSymbol& QwtLegendItem::symbol() const
{
return *d_data->symbol;
}
/*!
Set curve pen.
\param pen Curve pen
\sa curvePen()
*/
void QwtLegendItem::setCurvePen(const QPen &pen)
{
if ( pen != d_data->curvePen ) {
d_data->curvePen = pen;
update();
}
}
/*!
\return The curve pen.
\sa setCurvePen()
*/
const QPen& QwtLegendItem::curvePen() const
{
return d_data->curvePen;
}
/*!
Paint the identifier to a given rect.
\param painter Painter
\param rect Rect where to paint
*/
void QwtLegendItem::drawIdentifier(
QPainter *painter, const QRect &rect) const
{
if ( rect.isEmpty() )
return;
if ( (d_data->identifierMode & ShowLine ) && (d_data->curvePen.style() != Qt::NoPen) ) {
painter->save();
painter->setPen(d_data->curvePen);
QwtPainter::drawLine(painter, rect.left(), rect.center().y(),
rect.right(), rect.center().y());
painter->restore();
}
if ( (d_data->identifierMode & ShowSymbol)
&& (d_data->symbol->style() != QwtSymbol::NoSymbol) ) {
QSize symbolSize =
QwtPainter::metricsMap().screenToLayout(d_data->symbol->size());
// scale the symbol size down if it doesn't fit into rect.
if ( rect.width() < symbolSize.width() ) {
const double ratio =
double(symbolSize.width()) / double(rect.width());
symbolSize.setWidth(rect.width());
symbolSize.setHeight(qRound(symbolSize.height() / ratio));
}
if ( rect.height() < symbolSize.height() ) {
const double ratio =
double(symbolSize.width()) / double(rect.width());
symbolSize.setHeight(rect.height());
symbolSize.setWidth(qRound(symbolSize.width() / ratio));
}
QRect symbolRect;
symbolRect.setSize(symbolSize);
symbolRect.moveCenter(rect.center());
painter->save();
painter->setBrush(d_data->symbol->brush());
painter->setPen(d_data->symbol->pen());
d_data->symbol->draw(painter, symbolRect);
painter->restore();
}
}
/*!
Draw the legend item to a given rect.
\param painter Painter
\param rect Rect where to paint the button
*/
void QwtLegendItem::drawItem(QPainter *painter, const QRect &rect) const
{
painter->save();
const QwtMetricsMap &map = QwtPainter::metricsMap();
const int m = map.screenToLayoutX(margin());
const int spacing = map.screenToLayoutX(d_data->spacing);
const int identifierWidth = map.screenToLayoutX(d_data->identifierWidth);
const QRect identifierRect(rect.x() + m, rect.y(),
identifierWidth, rect.height());
drawIdentifier(painter, identifierRect);
// Label
QRect titleRect = rect;
titleRect.setX(identifierRect.right() + 2 * spacing);
text().draw(painter, titleRect);
painter->restore();
}
//! Paint event
void QwtLegendItem::paintEvent(QPaintEvent *e)
{
const QRect cr = contentsRect();
QPainter painter(this);
painter.setClipRegion(e->region());
if ( d_data->isDown ) {
qDrawWinButton(&painter, 0, 0, width(), height(),
#if QT_VERSION < 0x040000
colorGroup(),
#else
palette(),
#endif
true);
}
painter.save();
if ( d_data->isDown ) {
const QSize shiftSize = buttonShift(this);
painter.translate(shiftSize.width(), shiftSize.height());
}
painter.setClipRect(cr);
drawContents(&painter);
QRect rect = cr;
rect.setX(rect.x() + margin());
if ( d_data->itemMode != QwtLegend::ReadOnlyItem )
rect.setX(rect.x() + ButtonFrame);
rect.setWidth(d_data->identifierWidth);
drawIdentifier(&painter, rect);
painter.restore();
}
//! Handle mouse press events
void QwtLegendItem::mousePressEvent(QMouseEvent *e)
{
if ( e->button() == Qt::LeftButton ) {
switch(d_data->itemMode) {
case QwtLegend::ClickableItem: {
setDown(true);
return;
}
case QwtLegend::CheckableItem: {
setDown(!isDown());
return;
}
default:
;
}
}
QwtTextLabel::mousePressEvent(e);
}
//! Handle mouse release events
void QwtLegendItem::mouseReleaseEvent(QMouseEvent *e)
{
if ( e->button() == Qt::LeftButton ) {
switch(d_data->itemMode) {
case QwtLegend::ClickableItem: {
setDown(false);
return;
}
case QwtLegend::CheckableItem: {
return; // do nothing, but accept
}
default:
;
}
}
QwtTextLabel::mouseReleaseEvent(e);
}
//! Handle key press events
void QwtLegendItem::keyPressEvent(QKeyEvent *e)
{
if ( e->key() == Qt::Key_Space ) {
switch(d_data->itemMode) {
case QwtLegend::ClickableItem: {
if ( !e->isAutoRepeat() )
setDown(true);
return;
}
case QwtLegend::CheckableItem: {
if ( !e->isAutoRepeat() )
setDown(!isDown());
return;
}
default:
;
}
}
QwtTextLabel::keyPressEvent(e);
}
//! Handle key release events
void QwtLegendItem::keyReleaseEvent(QKeyEvent *e)
{
if ( e->key() == Qt::Key_Space ) {
switch(d_data->itemMode) {
case QwtLegend::ClickableItem: {
if ( !e->isAutoRepeat() )
setDown(false);
return;
}
case QwtLegend::CheckableItem: {
return; // do nothing, but accept
}
default:
;
}
}
QwtTextLabel::keyReleaseEvent(e);
}
/*!
Check/Uncheck a the item
\param on check/uncheck
\sa setItemMode()
*/
void QwtLegendItem::setChecked(bool on)
{
if ( d_data->itemMode == QwtLegend::CheckableItem ) {
const bool isBlocked = signalsBlocked();
blockSignals(true);
setDown(on);
blockSignals(isBlocked);
}
}
//! Return true, if the item is checked
bool QwtLegendItem::isChecked() const
{
return d_data->itemMode == QwtLegend::CheckableItem && isDown();
}
//! Set the item being down
void QwtLegendItem::setDown(bool down)
{
if ( down == d_data->isDown )
return;
d_data->isDown = down;
update();
if ( d_data->itemMode == QwtLegend::ClickableItem ) {
if ( d_data->isDown )
emit pressed();
else {
emit released();
emit clicked();
}
}
if ( d_data->itemMode == QwtLegend::CheckableItem )
emit checked(d_data->isDown);
}
//! Return true, if the item is down
bool QwtLegendItem::isDown() const
{
return d_data->isDown;
}
//! Return a size hint
QSize QwtLegendItem::sizeHint() const
{
QSize sz = QwtTextLabel::sizeHint();
if ( d_data->itemMode != QwtLegend::ReadOnlyItem )
sz += buttonShift(this);
return sz;
}
void QwtLegendItem::drawText(QPainter *painter, const QRect &rect)
{
QwtTextLabel::drawText(painter, rect);
}