Skip to content
qwt_picker.cpp 34.5 KiB
Newer Older
pixhawk's avatar
pixhawk committed
/* -*- 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
 *****************************************************************************/

#include <qapplication.h>
#include <qevent.h>
#include <qpainter.h>
#include <qframe.h>
#include <qcursor.h>
#include <qbitmap.h>
#include "qwt_math.h"
#include "qwt_painter.h"
#include "qwt_picker_machine.h"
#include "qwt_picker.h"
#if QT_VERSION < 0x040000
#include <qguardedptr.h>
#else
#include <qpointer.h>
#include <qpaintengine.h>
#endif

class QwtPicker::PickerWidget: public QWidget
{
public:
    enum Type
    {
        RubberBand,
        Text
    };

    PickerWidget(QwtPicker *, QWidget *, Type);
    virtual void updateMask();

    /*
       For a tracker text with a background we can use the background 
       rect as mask. Also for "regular" Qt widgets >= 4.3.0 we
       don't need to mask the text anymore.
     */
    bool d_hasTextMask;

protected:
    virtual void paintEvent(QPaintEvent *);

    QwtPicker *d_picker;
    Type d_type;
};

class QwtPicker::PrivateData
{
public:
    bool enabled;

    QwtPickerMachine *stateMachine;

    int selectionFlags;
    QwtPicker::ResizeMode resizeMode;

    QwtPicker::RubberBand rubberBand;
    QPen rubberBandPen;

    QwtPicker::DisplayMode trackerMode;
    QPen trackerPen;
    QFont trackerFont;

    QwtPolygon selection;
    bool isActive;
    QPoint trackerPosition;

    bool mouseTracking; // used to save previous value

    /*
      On X11 the widget below the picker widgets gets paint events
      with a region that is the bounding rect of the mask, if it is complex.
      In case of (f.e) a CrossRubberBand and a text this creates complete
      repaints of the widget. So we better use two different widgets.
     */
     
#if QT_VERSION < 0x040000
    QGuardedPtr<PickerWidget> rubberBandWidget;
    QGuardedPtr<PickerWidget> trackerWidget;
#else
    QPointer<PickerWidget> rubberBandWidget;
    QPointer<PickerWidget> trackerWidget;
#endif
};

QwtPicker::PickerWidget::PickerWidget(
        QwtPicker *picker, QWidget *parent, Type type):
    QWidget(parent),
    d_hasTextMask(false),
    d_picker(picker),
    d_type(type)
{
#if QT_VERSION >= 0x040000
    setAttribute(Qt::WA_TransparentForMouseEvents);
    setAttribute(Qt::WA_NoSystemBackground);
    setFocusPolicy(Qt::NoFocus);
#else
    setBackgroundMode(Qt::NoBackground);
    setFocusPolicy(QWidget::NoFocus);
    setMouseTracking(true);
#endif
    hide();
}

void QwtPicker::PickerWidget::updateMask()
{
    QRegion mask;

    if ( d_type == RubberBand )
    {
        QBitmap bm(width(), height());
        bm.fill(Qt::color0);

        QPainter painter(&bm);
        QPen pen = d_picker->rubberBandPen();
        pen.setColor(Qt::color1);
        painter.setPen(pen);

        d_picker->drawRubberBand(&painter);

        mask = QRegion(bm);
    }
    if ( d_type == Text )
    {
        d_hasTextMask = true;
#if QT_VERSION >= 0x040300
        if ( !parentWidget()->testAttribute(Qt::WA_PaintOnScreen) )
        {
#if 0
            if ( parentWidget()->paintEngine()->type() != QPaintEngine::OpenGL )
#endif
            {
                // With Qt >= 4.3 drawing of the tracker can be implemented in an
                // easier way, using the textRect as mask. 

                d_hasTextMask = false;
            }
        }
#endif
        
        if ( d_hasTextMask )
        {
            const QwtText label = d_picker->trackerText(
                d_picker->trackerPosition());
            if ( label.testPaintAttribute(QwtText::PaintBackground)
                && label.backgroundBrush().style() != Qt::NoBrush )
            {
#if QT_VERSION >= 0x040300
                if ( label.backgroundBrush().color().alpha() > 0 )
#endif
                // We don't need a text mask, when we have a background
                d_hasTextMask = false;
            }
        }

        if ( d_hasTextMask )
        {
            QBitmap bm(width(), height());
            bm.fill(Qt::color0);

            QPainter painter(&bm);
            painter.setFont(font());

            QPen pen = d_picker->trackerPen();
            pen.setColor(Qt::color1);
            painter.setPen(pen);

            d_picker->drawTracker(&painter);

            mask = QRegion(bm);
        }
        else
        {
            mask = d_picker->trackerRect(font());
        }
    }

#if QT_VERSION < 0x040000
    QWidget *w = parentWidget();
    const bool doUpdate = w->isUpdatesEnabled();
    const Qt::BackgroundMode bgMode = w->backgroundMode();
    w->setUpdatesEnabled(false);
    if ( bgMode != Qt::NoBackground )
        w->setBackgroundMode(Qt::NoBackground);
#endif

    setMask(mask);

#if QT_VERSION < 0x040000
    if ( bgMode != Qt::NoBackground )
        w->setBackgroundMode(bgMode);

    w->setUpdatesEnabled(doUpdate);
#endif
Loading
Loading full blame...