#include "designerView.h"
#include <QMouseEvent>

#define MAX_ZoomValue 50.0
#define MIN_ZoomValue 0.02

DesignerView::DesignerView(QWidget *parent)
    : QGraphicsView(parent)
{
    m_bMousePress = false;
    m_dScale = 1.0;
    initialize();
}
DesignerView::~DesignerView()
{

}

void DesignerView::initialize()
{
    //去掉QGraphicsView自带滚动条
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    //设置背景
    setStyleSheet("background-image: url(:/images/checkerboard.png);\
                  padding: 0px; \
                  border: 0px;");
    //打开反锯齿
    setRenderHint(QPainter::Antialiasing);
    setMouseTracking(true);
    //setDragMode(QGraphicsView::RubberBandDrag); //将控制交给selector

    centerOn(0, 0);
}

void DesignerView::contextMenuEvent(QContextMenuEvent* event)
{
    Q_UNUSED(event);
    m_bMousePress = false;
}

void DesignerView::mousePressEvent(QMouseEvent* event)
{
    QGraphicsItem* item = scene()->itemAt(mapToScene(event->pos()), transform());
    if (event->button() == Qt::MiddleButton /*&& !item*/) //在空白处按住中键进行拖动
    {
        m_bMousePress = true;
        setCursor(Qt::ClosedHandCursor);
        m_ptLatstMouse_view = event->pos();
    }
    else
        QGraphicsView::mousePressEvent(event);
}

void DesignerView::mouseMoveEvent(QMouseEvent* event)
{
    if(m_bMousePress)
    {
        QPointF mouseMoveLength = event->pos() - m_ptLatstMouse_view.toPoint();
        translate(mouseMoveLength);
        m_ptLatstMouse_view = event->pos();
    }
    else
        QGraphicsView::mouseMoveEvent(event);
}

void DesignerView::mouseReleaseEvent(QMouseEvent* event)
{
    if (event->button() == Qt::MiddleButton) //按住中键进行拖动
    {
        m_bMousePress = false;
        setCursor(Qt::ArrowCursor);
    }
    else
        QGraphicsView::mouseReleaseEvent(event);
}

void DesignerView::wheelEvent(QWheelEvent* event) //滚轮进行放大缩小
{
    QPointF mousePos = event->position();
    double angleDeltaY = event->angleDelta().y();
    double zoomFactor = qPow(1.0015, angleDeltaY); //可以实现更平滑的缩放
    zoom(mousePos, zoomFactor);

    //注意不要调用基类的滚轮函数，否则滚轮事件会映射到滚动条操作
    //QGraphicsView::wheelEvent(event);
}

double DesignerView::getScaleFactor()
{
    //QTransform为一个3*3的矩阵，m11和m22元素分别为水平和垂直的缩放值
    return this->transform().m11();
}

bool DesignerView::zoomLimit(double& value)
{
    m_dScale *= value;
    if(m_dScale >= MAX_ZoomValue)
    {
        m_dScale = MAX_ZoomValue;
        value = m_dScale / getScaleFactor();
    }
    else if(m_dScale <= MIN_ZoomValue)
    {
        m_dScale = MIN_ZoomValue;
        value = m_dScale / getScaleFactor();
    }

    if(qFabs(value - 1) < 0.01) //缩放因子近似为1
        return true;

    return false;
}

void DesignerView::zoom(const QPointF& mousePos, double zoomFactor)
{
    if(zoomLimit(zoomFactor))
        return;

    /*
     * QGraphicsView的默认transformationAnchor(变换锚点)是AnchorViewCenter，也就是中心，此处希望以鼠标指向为变换中心,
     * AnchorUnderMouse可以实现，但经尝试没有自己进行移动(translate)效果好，所以先设置成NoAnchor,变换后再设置回来
    */
    ViewportAnchor lastAnchor = this->transformationAnchor();
    setTransformationAnchor(QGraphicsView::NoAnchor);
    QPointF targetScenePos = mapToScene(mousePos.toPoint());
    QTransform trans = transform();
    trans.translate(targetScenePos.x(), targetScenePos.y());
    trans.scale(zoomFactor, zoomFactor);
    trans.translate(-targetScenePos.x(), -targetScenePos.y());
    setTransform(trans);
    setTransformationAnchor(lastAnchor);
}

void DesignerView::zoomIn()
{
    //以view的中心点作为放大中心
    double dWidth_View = viewport()->width();
    double dHeight_View = viewport()->height();
    QPoint pt(dWidth_View * 0.5, dHeight_View * 0.5);
    zoom(pt, 1.1);
}

void DesignerView::zoomOut()
{
    //以view的中心点作为缩小中心
    double dWidth_View = viewport()->width();
    double dHeight_View = viewport()->height();
    QPoint pt(dWidth_View * 0.5, dHeight_View * 0.5);
    zoom(pt, 0.9);
}

void DesignerView::zoomFit()
{
    resetTransform();

    double dWidth_View = viewport()->width();
    double dHeight_View = viewport()->height();
    double dWidth_Scene = scene()->sceneRect().width();
    double dHeight_Scene = scene()->sceneRect().height();

    double dWidthScale = dWidth_View / dWidth_Scene;
    double dHeightScale = dHeight_View / dHeight_Scene;
    m_dScale = qMin(dWidthScale, dHeightScale);

    QTransform trans = transform();
    trans.scale(m_dScale, m_dScale);
    setTransform(trans);
    centerOn(0, 0);
}

void DesignerView::translate(const QPointF& delta)
{
    ViewportAnchor lastAnchor = this->transformationAnchor();
    setTransformationAnchor(QGraphicsView::NoAnchor);
    QTransform trans = transform();
    trans.translate(delta.x(), delta.y());
    setTransform(trans);
    setTransformationAnchor(lastAnchor);
}
