void VIEW::SetViewport( const BOX2D& aViewport )
{
    VECTOR2D ssize = ToWorld( m_gal->GetScreenPixelSize(), false );

    wxASSERT( ssize.x > 0 && ssize.y > 0 );

    VECTOR2D centre = aViewport.Centre();
    VECTOR2D vsize  = aViewport.GetSize();
    double   zoom   = 1.0 / std::max( fabs( vsize.x / ssize.x ), fabs( vsize.y / ssize.y ) );

    SetCenter( centre );
    SetScale( GetScale() * zoom );
}
void WX_VIEW_CONTROLS::UpdateScrollbars()
{
    const BOX2D viewport = m_view->GetViewport();
    const BOX2D& boundary = m_view->GetBoundary();

    m_scrollScale.x = 2e3 / viewport.GetWidth();    // TODO it does not have to be updated so often
    m_scrollScale.y = 2e3 / viewport.GetHeight();
    VECTOR2I newScroll( ( viewport.Centre().x - boundary.GetLeft() ) * m_scrollScale.x,
                ( viewport.Centre().y - boundary.GetTop() ) * m_scrollScale.y );

    // Flip scroll direction in flipped view
    if( m_view->IsMirroredX() )
        newScroll.x = ( boundary.GetRight() - viewport.Centre().x ) * m_scrollScale.x;

    // Adjust scrollbars only if it is needed. Otherwise there are cases when canvas is continuosly
    // refreshed (Windows)
    if( m_scrollPos != newScroll )
    {
        // Another example of wxWidgets being broken by design: scroll position is determined by the
        // left (or top, if vertical) edge of the slider. Fortunately, slider size seems to be constant
        // (at least for wxGTK and wxMSW), so we have to add its size to allow user to scroll the workspace
        // till the end.

        m_parentPanel->SetScrollbars( 1, 1,
#if defined(__LINUX__)
            m_scrollScale.x * boundary.GetWidth() + 1623, m_scrollScale.y * boundary.GetHeight() + 1623,
#elif defined(__WIN32__) || defined(__WIN64__)
            m_scrollScale.x * boundary.GetWidth() + 1377, m_scrollScale.y * boundary.GetHeight() + 741,
#else
            m_scrollScale.x * boundary.GetWidth(), m_scrollScale.y * boundary.GetHeight(),
#endif
            newScroll.x, newScroll.y, false );

        m_scrollPos = newScroll;
    }
}
void WX_VIEW_CONTROLS::UpdateScrollbars()
{
    const BOX2D viewport = m_view->GetViewport();
    const BOX2I& boundary = m_view->GetBoundary();

    m_scrollScale.x = 2e3 * boundary.GetWidth() / viewport.GetWidth();
    m_scrollScale.y = 2e3 * boundary.GetHeight() / viewport.GetHeight();

    // Another example of wxWidgets being broken by design: scroll position is determined by the
    // left (or top, if vertical) edge of the slider. Fortunately, slider size seems to be constant
    // (at least for wxGTK 3.0), so we have to add its size to allow user to scroll the workspace
    // till the end.
    m_parentPanel->SetScrollbars( 1, 1,
#ifdef __LINUX__
            m_scrollScale.x + 1623, m_scrollScale.y + 1623,
#else
            m_scrollScale.x, m_scrollScale.y,
#endif
            ( viewport.Centre().x - boundary.GetLeft() ) / boundary.GetWidth() * m_scrollScale.x,
            ( viewport.Centre().y - boundary.GetTop() ) / boundary.GetHeight() * m_scrollScale.y );
}