void ContentWindowGraphicsItem::drawMovieControls_( QPainter* painter )
{
    ContentWindowManagerPtr contentWindowManager = getContentWindowManager();

    float buttonWidth, buttonHeight;
    getButtonDimensions(buttonWidth, buttonHeight);

    QPen pen;

    if( contentWindowManager->getContent()->getType() == CONTENT_TYPE_MOVIE &&
        g_configuration->getOptions()->getShowMovieControls( ))
    {
        // play/pause
        QRectF playPauseRect(coordinates_.x() + coordinates_.width()/2 - buttonWidth, coordinates_.y() + coordinates_.height() - buttonHeight,
                              buttonWidth, buttonHeight);
        pen.setColor(QColor(contentWindowManager->getControlState() & STATE_PAUSED ? 128 :200,0,0));
        painter->setPen(pen);
        painter->fillRect(playPauseRect, pen.color());

        // loop
        QRectF loopRect(coordinates_.x() + coordinates_.width()/2, coordinates_.y() + coordinates_.height() - buttonHeight,
                        buttonWidth, buttonHeight);
        pen.setColor(QColor(0,contentWindowManager->getControlState() & STATE_LOOP ? 200 :128,0));
        painter->setPen(pen);
        painter->fillRect(loopRect, pen.color());
    }
}
void ContentWindowGraphicsItem::drawFullscreenButton_( QPainter* painter )
{
    float buttonWidth, buttonHeight;
    getButtonDimensions(buttonWidth, buttonHeight);

    QRectF fullscreenRect(coordinates_.x(), coordinates_.y() + coordinates_.height() - buttonHeight, buttonWidth, buttonHeight);
    QPen pen;
    pen.setColor(QColor(128,128,128));
    painter->setPen(pen);
    painter->drawRect(fullscreenRect);
}
void ContentWindowGraphicsItem::drawResizeIndicator_( QPainter* painter )
{
    float buttonWidth, buttonHeight;
    getButtonDimensions(buttonWidth, buttonHeight);

    QRectF resizeRect(coordinates_.x() + coordinates_.width() - buttonWidth, coordinates_.y() + coordinates_.height() - buttonHeight, buttonWidth, buttonHeight);
    QPen pen;
    pen.setColor(QColor(128,128,128));
    painter->setPen(pen);
    painter->drawRect(resizeRect);
    painter->drawLine(QPointF(coordinates_.x() + coordinates_.width(), coordinates_.y() + coordinates_.height() - buttonHeight),
                      QPointF(coordinates_.x() + coordinates_.width() - buttonWidth, coordinates_.y() + coordinates_.height()));
}
void ContentWindowGraphicsItem::drawCloseButton_( QPainter* painter )
{
    float buttonWidth, buttonHeight;
    getButtonDimensions(buttonWidth, buttonHeight);

    QRectF closeRect(coordinates_.x() + coordinates_.width() - buttonWidth, coordinates_.y(), buttonWidth, buttonHeight);
    QPen pen;
    pen.setColor(QColor(255,0,0));
    painter->setPen(pen);
    painter->drawRect(closeRect);
    painter->drawLine(QPointF(coordinates_.x() + coordinates_.width() - buttonWidth, coordinates_.y()),
                      QPointF(coordinates_.x() + coordinates_.width(), coordinates_.y() + buttonHeight));
    painter->drawLine(QPointF(coordinates_.x() + coordinates_.width(), coordinates_.y()),
                      QPointF(coordinates_.x() + coordinates_.width() - buttonWidth, coordinates_.y() + buttonHeight));
}
void ContentWindowGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
    // on Mac we've seen that mouse events can go to the wrong graphics item
    // this is due to the bug: https://bugreports.qt.nokia.com/browse/QTBUG-20493
    // here we ignore the event if it shouldn't have been sent to us, which ensures
    // it will go to the correct item...
    if(boundingRect().contains(event->pos()) == false)
    {
        event->ignore();
        return;
    }

    // button dimensions
    float buttonWidth, buttonHeight;
    getButtonDimensions(buttonWidth, buttonHeight);

    // item rectangle and event position
    QRectF r = rect();
    QPointF eventPos = event->pos();

    // check to see if user clicked on the close button
    if(fabs((r.x()+r.width()) - eventPos.x()) <= buttonWidth && fabs((r.y()) - eventPos.y()) <= buttonHeight)
    {
        close();

        return;
    }

    // check to see if user clicked on the resize button
    if(fabs((r.x()+r.width()) - eventPos.x()) <= buttonWidth && fabs((r.y()+r.height()) - eventPos.y()) <= buttonHeight)
    {
        resizing_ = true;
    }

    // move to the front of the GUI display
    moveToFront();

    QGraphicsItem::mousePressEvent(event);
}
void ContentWindowGraphicsItem::drawTextLabel_( QPainter* painter )
{
    ContentWindowManagerPtr contentWindowManager = getContentWindowManager();

    float buttonWidth, buttonHeight;
    getButtonDimensions(buttonWidth, buttonHeight);

    const float fontSize = 24.;

    QFont font;
    font.setPixelSize(fontSize);
    painter->setFont(font);

    // color the text black
    QPen pen;
    pen.setColor(QColor(0,0,0));
    painter->setPen(pen);

    // scale the text size down to the height of the graphics view
    // and, calculate the bounding rectangle for the text based on this scale
    // the dimensions of the view need to be corrected for the tiled display aspect ratio
    // recall the tiled display UI is only part of the graphics view since we show it at the correct aspect ratio
    // TODO refactor this for clarity!
    float viewWidth = (float)scene()->views()[0]->width();
    float viewHeight = (float)scene()->views()[0]->height();

    const float tiledDisplayAspect = g_configuration->getAspectRatio();

    if(viewWidth / viewHeight > tiledDisplayAspect)
    {
        viewWidth = viewHeight * tiledDisplayAspect;
    }
    else if(viewWidth / viewHeight <= tiledDisplayAspect)
    {
        viewHeight = viewWidth / tiledDisplayAspect;
    }

    float verticalTextScale = 1. / viewHeight;
    float horizontalTextScale = viewHeight / viewWidth * verticalTextScale;

    painter->scale(horizontalTextScale, verticalTextScale);

    QRectF textBoundingRect = QRectF(coordinates_.x() / horizontalTextScale,
                                     coordinates_.y() / verticalTextScale,
                                     coordinates_.width() / horizontalTextScale,
                                     coordinates_.height() / verticalTextScale);

    // get the label and render it
    QString label(contentWindowManager->getContent()->getURI());
    QString labelSection = label.section("/", -1, -1).prepend(" ");
    painter->drawText(textBoundingRect, Qt::AlignLeft | Qt::AlignTop, labelSection);

    // draw window info at smaller scale
    verticalTextScale *= 0.5;
    horizontalTextScale *= 0.5;

    painter->scale(0.5, 0.5);

    textBoundingRect = QRectF((coordinates_.x()+buttonWidth) / horizontalTextScale,
                               coordinates_.y() / verticalTextScale,
                              (coordinates_.width()-buttonWidth) / horizontalTextScale,
                               coordinates_.height() / verticalTextScale);

    QString coordinatesLabel = QString(" (") + QString::number(coordinates_.x(), 'f', 2) + QString(" ,") +
                                               QString::number(coordinates_.y(), 'f', 2) + QString(", ") +
                                               QString::number(coordinates_.width(), 'f', 2) + QString(", ") +
                                               QString::number(coordinates_.height(), 'f', 2) + QString(")\n");
    QString zoomCenterLabel = QString(" zoom = ") + QString::number(zoom_, 'f', 2) + QString(" @ (") +
                              QString::number(centerX_, 'f', 2) + QString(", ") +
                              QString::number(centerY_, 'f', 2) + QString(")");
    QString interactionLabel = QString(" x: ") +
            QString::number(latestEvent_.mouseX, 'f', 2) +
            QString(" y: ") + QString::number(latestEvent_.mouseY, 'f', 2) +
            QString(" mouseLeft: ") + QString::number((int) latestEvent_.mouseLeft, 'b', 1) +
            QString(" mouseMiddle: ") + QString::number((int) latestEvent_.mouseMiddle, 'b', 1) +
            QString(" mouseRight: ") + QString::number((int) latestEvent_.mouseRight, 'b', 1);

    QString windowInfoLabel = coordinatesLabel + zoomCenterLabel + interactionLabel;
    painter->drawText(textBoundingRect, Qt::AlignLeft | Qt::AlignBottom, windowInfoLabel);
}
void ContentWindowGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
    // on Mac we've seen that mouse events can go to the wrong graphics item
    // this is due to the bug: https://bugreports.qt.nokia.com/browse/QTBUG-20493
    // here we ignore the event if it shouldn't have been sent to us, which ensures
    // it will go to the correct item...
    if(boundingRect().contains(event->pos()) == false)
    {
        event->ignore();
        return;
    }

    // button dimensions
    float buttonWidth, buttonHeight;
    getButtonDimensions(buttonWidth, buttonHeight);

    // item rectangle and event position
    QRectF r = boundingRect();
    QPointF eventPos = event->pos();

    // check to see if user clicked on the close button
    if(fabs((r.x()+r.width()) - eventPos.x()) <= buttonWidth &&
       fabs(r.y() - eventPos.y()) <= buttonHeight)
    {
        close();

        return;
    }

    // move to the front of the GUI display
    moveToFront();

    ContentWindowManagerPtr contentWindow = getContentWindowManager();
    if (!contentWindow)
        return;

    if (selected())
    {
        contentWindow->getInteractionDelegate().mousePressEvent(event);
        return;
    }

    contentWindow->getContent()->blockAdvance( true );

    // check to see if user clicked on the resize button
    if(fabs((r.x()+r.width()) - eventPos.x()) <= buttonWidth &&
       fabs((r.y()+r.height()) - eventPos.y()) <= buttonHeight)
    {
        resizing_ = true;
    }
    // check to see if user clicked on the fullscreen button
    else if(fabs(r.x() - eventPos.x()) <= buttonWidth &&
            fabs((r.y()+r.height()) - eventPos.y()) <= buttonHeight)
    {
        toggleFullscreen();
    }
    else if(fabs(((r.x()+r.width())/2) - eventPos.x() - buttonWidth) <= buttonWidth &&
            fabs((r.y()+r.height()) - eventPos.y()) <= buttonHeight &&
            g_configuration->getOptions()->getShowMovieControls( ))
    {
        contentWindow->setControlState( ControlState(contentWindow->getControlState() ^ STATE_PAUSED) );
    }
    else if(fabs(((r.x()+r.width())/2) - eventPos.x()) <= buttonWidth &&
            fabs((r.y()+r.height()) - eventPos.y()) <= buttonHeight &&
            g_configuration->getOptions()->getShowMovieControls( ))
    {
        contentWindow->setControlState( ControlState(contentWindow->getControlState() ^ STATE_LOOP) );
    }
    else
        moving_ = true;

    QGraphicsItem::mousePressEvent(event);
}
void ContentWindowGraphicsItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
{
    QGraphicsRectItem::paint(painter, option, widget);

    boost::shared_ptr<ContentWindowManager> contentWindowManager = getContentWindowManager();

    if(contentWindowManager != NULL)
    {
        // default pen
        QPen pen;

        // button dimensions
        float buttonWidth, buttonHeight;
        getButtonDimensions(buttonWidth, buttonHeight);

        // draw close button
        QRectF closeRect(rect().x() + rect().width() - buttonWidth, rect().y(), buttonWidth, buttonHeight);
        pen.setColor(QColor(255,0,0));
        painter->setPen(pen);
        painter->drawRect(closeRect);
        painter->drawLine(QPointF(rect().x() + rect().width() - buttonWidth, rect().y()), QPointF(rect().x() + rect().width(), rect().y() + buttonHeight));
        painter->drawLine(QPointF(rect().x() + rect().width(), rect().y()), QPointF(rect().x() + rect().width() - buttonWidth, rect().y() + buttonHeight));

        // resize indicator
        QRectF resizeRect(rect().x() + rect().width() - buttonWidth, rect().y() + rect().height() - buttonHeight, buttonWidth, buttonHeight);
        pen.setColor(QColor(128,128,128));
        painter->setPen(pen);
        painter->drawRect(resizeRect);
        painter->drawLine(QPointF(rect().x() + rect().width(), rect().y() + rect().height() - buttonHeight), QPointF(rect().x() + rect().width() - buttonWidth, rect().y() + rect().height()));

        // text label

        // set the font
        float fontSize = 24.;

        QFont font;
        font.setPixelSize(fontSize);
        painter->setFont(font);

        // color the text black
        pen.setColor(QColor(0,0,0));
        painter->setPen(pen);

        // scale the text size down to the height of the graphics view
        // and, calculate the bounding rectangle for the text based on this scale
        // the dimensions of the view need to be corrected for the tiled display aspect ratio
        // recall the tiled display UI is only part of the graphics view since we show it at the correct aspect ratio
        float viewWidth = (float)scene()->views()[0]->width();
        float viewHeight = (float)scene()->views()[0]->height();

        float tiledDisplayAspect = (float)g_configuration->getTotalWidth() / (float)g_configuration->getTotalHeight();

        if(viewWidth / viewHeight > tiledDisplayAspect)
        {
            viewWidth = viewHeight * tiledDisplayAspect;
        }
        else if(viewWidth / viewHeight <= tiledDisplayAspect)
        {
            viewHeight = viewWidth / tiledDisplayAspect;
        }

        float verticalTextScale = 1. / viewHeight;
        float horizontalTextScale = viewHeight / viewWidth * verticalTextScale;

        painter->scale(horizontalTextScale, verticalTextScale);

        QRectF textBoundingRect = QRectF(rect().x() / horizontalTextScale, rect().y() / verticalTextScale, rect().width() / horizontalTextScale, rect().height() / verticalTextScale);

        // get the label and render it
        QString label(contentWindowManager->getContent()->getURI().c_str());
        QString labelSection = label.section("/", -1, -1).prepend(" ");
        painter->drawText(textBoundingRect, Qt::AlignLeft | Qt::AlignTop, labelSection);

        // draw window info at smaller scale
        verticalTextScale *= 0.5;
        horizontalTextScale *= 0.5;

        painter->scale(0.5, 0.5);

        textBoundingRect = QRectF(rect().x() / horizontalTextScale, rect().y() / verticalTextScale, rect().width() / horizontalTextScale, rect().height() / verticalTextScale);

        QString coordinatesLabel = QString(" (") + QString::number(x_, 'f', 2) + QString(" ,") + QString::number(y_, 'f', 2) + QString(", ") + QString::number(w_, 'f', 2) + QString(", ") + QString::number(h_, 'f', 2) + QString(")\n");
        QString zoomCenterLabel = QString(" zoom = ") + QString::number(zoom_, 'f', 2) + QString(" @ (") + QString::number(centerX_, 'f', 2) + QString(", ") + QString::number(centerY_, 'f', 2) + QString(")");
        QString interactionLabel = QString(" x: ") +
                                   QString::number(interactionState_.mouseX_, 'f', 2) +
                                   QString(" y: ") + QString::number(interactionState_.mouseY_, 'f', 2) +
                                   QString(" mouseLeft: ") + QString::number((int) interactionState_.mouseLeft_, 'b', 1) +
                                   QString(" mouseMiddle: ") + QString::number((int) interactionState_.mouseMiddle_, 'b', 1) +
                                   QString(" mouseRight: ") + QString::number((int) interactionState_.mouseRight_, 'b', 1);

        QString windowInfoLabel = coordinatesLabel + zoomCenterLabel + interactionLabel;
        painter->drawText(textBoundingRect, Qt::AlignLeft | Qt::AlignBottom, windowInfoLabel);
    }
}