scrlwing.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,388 行 · 第 1/3 页

CPP
1,388
字号
{
    int nScrollInc = CalcScrollInc(event);
    if ( nScrollInc == 0 )
    {
        // can't scroll further
        event.Skip();

        return;
    }

    int orient = event.GetOrientation();
    if (orient == wxHORIZONTAL)
    {
        m_xScrollPosition += nScrollInc;
        m_win->SetScrollPos(wxHORIZONTAL, m_xScrollPosition);
    }
    else
    {
        m_yScrollPosition += nScrollInc;
        m_win->SetScrollPos(wxVERTICAL, m_yScrollPosition);
    }

    bool needsRefresh = false;
    int dx = 0,
        dy = 0;
    if (orient == wxHORIZONTAL)
    {
       if ( m_xScrollingEnabled )
       {
           dx = -m_xScrollPixelsPerLine * nScrollInc;
       }
       else
       {
           needsRefresh = true;
       }
    }
    else
    {
        if ( m_yScrollingEnabled )
        {
            dy = -m_yScrollPixelsPerLine * nScrollInc;
        }
        else
        {
            needsRefresh = true;
        }
    }

    if ( needsRefresh )
    {
        m_targetWindow->Refresh(true, GetScrollRect());
    }
    else
    {
        m_targetWindow->ScrollWindow(dx, dy, GetScrollRect());
    }
}

int wxScrollHelper::CalcScrollInc(wxScrollWinEvent& event)
{
    int pos = event.GetPosition();
    int orient = event.GetOrientation();

    int nScrollInc = 0;
    if (event.GetEventType() == wxEVT_SCROLLWIN_TOP)
    {
            if (orient == wxHORIZONTAL)
                nScrollInc = - m_xScrollPosition;
            else
                nScrollInc = - m_yScrollPosition;
    } else
    if (event.GetEventType() == wxEVT_SCROLLWIN_BOTTOM)
    {
            if (orient == wxHORIZONTAL)
                nScrollInc = m_xScrollLines - m_xScrollPosition;
            else
                nScrollInc = m_yScrollLines - m_yScrollPosition;
    } else
    if (event.GetEventType() == wxEVT_SCROLLWIN_LINEUP)
    {
            nScrollInc = -1;
    } else
    if (event.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN)
    {
            nScrollInc = 1;
    } else
    if (event.GetEventType() == wxEVT_SCROLLWIN_PAGEUP)
    {
            if (orient == wxHORIZONTAL)
                nScrollInc = -GetScrollPageSize(wxHORIZONTAL);
            else
                nScrollInc = -GetScrollPageSize(wxVERTICAL);
    } else
    if (event.GetEventType() == wxEVT_SCROLLWIN_PAGEDOWN)
    {
            if (orient == wxHORIZONTAL)
                nScrollInc = GetScrollPageSize(wxHORIZONTAL);
            else
                nScrollInc = GetScrollPageSize(wxVERTICAL);
    } else
    if ((event.GetEventType() == wxEVT_SCROLLWIN_THUMBTRACK) ||
        (event.GetEventType() == wxEVT_SCROLLWIN_THUMBRELEASE))
    {
            if (orient == wxHORIZONTAL)
                nScrollInc = pos - m_xScrollPosition;
            else
                nScrollInc = pos - m_yScrollPosition;
    }

    if (orient == wxHORIZONTAL)
    {
        if (m_xScrollPixelsPerLine > 0)
        {
            if ( m_xScrollPosition + nScrollInc < 0 )
            {
                // As -ve as we can go
                nScrollInc = -m_xScrollPosition;
            }
            else // check for the other bound
            {
                const int posMax = m_xScrollLines - m_xScrollLinesPerPage;
                if ( m_xScrollPosition + nScrollInc > posMax )
                {
                    // As +ve as we can go
                    nScrollInc = posMax - m_xScrollPosition;
                }
            }
        }
        else
            m_targetWindow->Refresh(true, GetScrollRect());
    }
    else
    {
        if ( m_yScrollPixelsPerLine > 0 )
        {
            if ( m_yScrollPosition + nScrollInc < 0 )
            {
                // As -ve as we can go
                nScrollInc = -m_yScrollPosition;
            }
            else // check for the other bound
            {
                const int posMax = m_yScrollLines - m_yScrollLinesPerPage;
                if ( m_yScrollPosition + nScrollInc > posMax )
                {
                    // As +ve as we can go
                    nScrollInc = posMax - m_yScrollPosition;
                }
            }
        }
        else
        {
            // VZ: why do we do this? (FIXME)
            m_targetWindow->Refresh(true, GetScrollRect());
        }
    }

    return nScrollInc;
}

// Adjust the scrollbars - new version.
void wxScrollHelper::AdjustScrollbars()
{
    static wxRecursionGuardFlag s_flagReentrancy;
    wxRecursionGuard guard(s_flagReentrancy);
    if ( guard.IsInside() )
    {
        // don't reenter AdjustScrollbars() while another call to
        // AdjustScrollbars() is in progress because this may lead to calling
        // ScrollWindow() twice and this can really happen under MSW if
        // SetScrollbar() call below adds or removes the scrollbar which
        // changes the window size and hence results in another
        // AdjustScrollbars() call
        return;
    }

    int w = 0, h = 0;
    int oldw, oldh;

    int oldXScroll = m_xScrollPosition;
    int oldYScroll = m_yScrollPosition;

    // VZ: at least under Windows this loop is useless because when scrollbars
    //     [dis]appear we get a WM_SIZE resulting in another call to
    //     AdjustScrollbars() anyhow. As it doesn't seem to do any harm I leave
    //     it here for now but it would be better to ensure that all ports
    //     generate EVT_SIZE when scrollbars [dis]appear, emulating it if
    //     necessary, and remove it later
    // JACS: Stop potential infinite loop by limiting number of iterations
    int iterationCount = 0;
    const int iterationMax = 5;
    do
    {
        iterationCount ++;
        
        GetTargetSize(&w, 0);

        // scroll lines per page: if 0, no scrolling is needed
        int linesPerPage;

        if ( m_xScrollPixelsPerLine == 0 )
        {
            // scrolling is disabled
            m_xScrollLines = 0;
            m_xScrollPosition = 0;
            linesPerPage = 0;
        }
        else // might need scrolling
        {
            // Round up integer division to catch any "leftover" client space.
            const int wVirt = m_targetWindow->GetVirtualSize().GetWidth();
            m_xScrollLines = (wVirt + m_xScrollPixelsPerLine - 1) / m_xScrollPixelsPerLine;

            // Calculate page size i.e. number of scroll units you get on the
            // current client window.
            linesPerPage = w / m_xScrollPixelsPerLine;

            // Special case. When client and virtual size are very close but
            // the client is big enough, kill scrollbar.
            if ((linesPerPage < m_xScrollLines) && (w >= wVirt)) ++linesPerPage;

            if (linesPerPage >= m_xScrollLines)
            {
                // we're big enough to not need scrolling
                linesPerPage =
                m_xScrollLines =
                m_xScrollPosition = 0;
            }
            else // we do need a scrollbar
            {
                if ( linesPerPage < 1 )
                    linesPerPage = 1;

                // Correct position if greater than extent of canvas minus
                // the visible portion of it or if below zero
                const int posMax = m_xScrollLines - linesPerPage;
                if ( m_xScrollPosition > posMax )
                    m_xScrollPosition = posMax;
                else if ( m_xScrollPosition < 0 )
                    m_xScrollPosition = 0;
            }
        }

        m_win->SetScrollbar(wxHORIZONTAL, m_xScrollPosition,
                            linesPerPage, m_xScrollLines);

        // The amount by which we scroll when paging
        SetScrollPageSize(wxHORIZONTAL, linesPerPage);

        GetTargetSize(0, &h);

        if ( m_yScrollPixelsPerLine == 0 )
        {
            // scrolling is disabled
            m_yScrollLines = 0;
            m_yScrollPosition = 0;
            linesPerPage = 0;
        }
        else // might need scrolling
        {
            // Round up integer division to catch any "leftover" client space.
            const int hVirt = m_targetWindow->GetVirtualSize().GetHeight();
            m_yScrollLines = ( hVirt + m_yScrollPixelsPerLine - 1 ) / m_yScrollPixelsPerLine;

            // Calculate page size i.e. number of scroll units you get on the
            // current client window.
            linesPerPage = h / m_yScrollPixelsPerLine;

            // Special case. When client and virtual size are very close but
            // the client is big enough, kill scrollbar.
            if ((linesPerPage < m_yScrollLines) && (h >= hVirt)) ++linesPerPage;

            if (linesPerPage >= m_yScrollLines)
            {
                // we're big enough to not need scrolling
                linesPerPage =
                m_yScrollLines =
                m_yScrollPosition = 0;
            }
            else // we do need a scrollbar
            {
                if ( linesPerPage < 1 )
                    linesPerPage = 1;

                // Correct position if greater than extent of canvas minus
                // the visible portion of it or if below zero
                const int posMax = m_yScrollLines - linesPerPage;
                if ( m_yScrollPosition > posMax )
                    m_yScrollPosition = posMax;
                else if ( m_yScrollPosition < 0 )
                    m_yScrollPosition = 0;
            }
        }

        m_win->SetScrollbar(wxVERTICAL, m_yScrollPosition,
                            linesPerPage, m_yScrollLines);

        // The amount by which we scroll when paging
        SetScrollPageSize(wxVERTICAL, linesPerPage);


        // If a scrollbar (dis)appeared as a result of this, adjust them again.
        oldw = w;
        oldh = h;

        GetTargetSize( &w, &h );
    } while ( (w != oldw || h != oldh) && (iterationCount < iterationMax) );

#ifdef __WXMOTIF__
    // Sorry, some Motif-specific code to implement a backing pixmap
    // for the wxRETAINED style. Implementing a backing store can't
    // be entirely generic because it relies on the wxWindowDC implementation
    // to duplicate X drawing calls for the backing pixmap.

    if ( m_targetWindow->GetWindowStyle() & wxRETAINED )
    {
        Display* dpy = XtDisplay((Widget)m_targetWindow->GetMainWidget());

        int totalPixelWidth = m_xScrollLines * m_xScrollPixelsPerLine;
        int totalPixelHeight = m_yScrollLines * m_yScrollPixelsPerLine;
        if (m_targetWindow->GetBackingPixmap() &&
           !((m_targetWindow->GetPixmapWidth() == totalPixelWidth) &&
             (m_targetWindow->GetPixmapHeight() == totalPixelHeight)))
        {
            XFreePixmap (dpy, (Pixmap) m_targetWindow->GetBackingPixmap());
            m_targetWindow->SetBackingPixmap((WXPixmap) 0);
        }

        if (!m_targetWindow->GetBackingPixmap() &&
           (m_xScrollLines != 0) && (m_yScrollLines != 0))
        {
            int depth = wxDisplayDepth();
            m_targetWindow->SetPixmapWidth(totalPixelWidth);
            m_targetWindow->SetPixmapHeight(totalPixelHeight);
            m_targetWindow->SetBackingPixmap((WXPixmap) XCreatePixmap (dpy, RootWindow (dpy, DefaultScreen (dpy)),
              m_targetWindow->GetPixmapWidth(), m_targetWindow->GetPixmapHeight(), depth));
        }

    }
#endif // Motif

    if (oldXScroll != m_xScrollPosition)
    {
       if (m_xScrollingEnabled)
            m_targetWindow->ScrollWindow( m_xScrollPixelsPerLine * (oldXScroll - m_xScrollPosition), 0,
                                          GetScrollRect() );
       else
            m_targetWindow->Refresh(true, GetScrollRect());
    }

    if (oldYScroll != m_yScrollPosition)
    {
        if (m_yScrollingEnabled)
            m_targetWindow->ScrollWindow( 0, m_yScrollPixelsPerLine * (oldYScroll-m_yScrollPosition),
                                          GetScrollRect() );
        else
            m_targetWindow->Refresh(true, GetScrollRect());
    }
}

void wxScrollHelper::DoPrepareDC(wxDC& dc)
{
    wxPoint pt = dc.GetDeviceOrigin();
    dc.SetDeviceOrigin( pt.x - m_xScrollPosition * m_xScrollPixelsPerLine,
                        pt.y - m_yScrollPosition * m_yScrollPixelsPerLine );
    dc.SetUserScale( m_scaleX, m_scaleY );
}

void wxScrollHelper::SetScrollRate( int xstep, int ystep )
{
    int old_x = m_xScrollPixelsPerLine * m_xScrollPosition;
    int old_y = m_yScrollPixelsPerLine * m_yScrollPosition;

    m_xScrollPixelsPerLine = xstep;
    m_yScrollPixelsPerLine = ystep;

    int new_x = m_xScrollPixelsPerLine * m_xScrollPosition;
    int new_y = m_yScrollPixelsPerLine * m_yScrollPosition;

    m_win->SetScrollPos( wxHORIZONTAL, m_xScrollPosition );
    m_win->SetScrollPos( wxVERTICAL, m_yScrollPosition );
    m_targetWindow->ScrollWindow( old_x - new_x, old_y - new_y );

    AdjustScrollbars();
}

void wxScrollHelper::GetScrollPixelsPerUnit (int *x_unit, int *y_unit) const
{
    if ( x_unit )
        *x_unit = m_xScrollPixelsPerLine;
    if ( y_unit )
        *y_unit = m_yScrollPixelsPerLine;
}

int wxScrollHelper::GetScrollPageSize(int orient) const
{
    if ( orient == wxHORIZONTAL )
        return m_xScrollLinesPerPage;
    else
        return m_yScrollLinesPerPage;
}

void wxScrollHelper::SetScrollPageSize(int orient, int pageSize)
{
    if ( orient == wxHORIZONTAL )
        m_xScrollLinesPerPage = pageSize;
    else
        m_yScrollLinesPerPage = pageSize;
}

/*
 * Scroll to given position (scroll position, not pixel position)
 */
void wxScrollHelper::Scroll( int x_pos, int y_pos )
{
    if (!m_targetWindow)
        return;

    if (((x_pos == -1) || (x_pos == m_xScrollPosition)) &&
        ((y_pos == -1) || (y_pos == m_yScrollPosition))) return;

    int w, h;
    GetTargetSize(&w, &h);

    if ((x_pos != -1) && (m_xScrollPixelsPerLine))
    {
        int old_x = m_xScrollPosition;
        m_xScrollPosition = x_pos;

        // Calculate page size i.e. number of scroll units you get on the
        // current client window
        int noPagePositions = (int) ( (w/(double)m_xScrollPixelsPerLine) + 0.5 );
        if (noPagePositions < 1) noPagePositions = 1;

        // Correct position if greater than extent of canvas minus
        // the visible portion of it or if below zero
        m_xScrollPosition = wxMin( m_xScrollLines-noPagePositions, m_xScrollPosition );
        m_xScrollPosition = wxMax( 0, m_xScrollPosition );

        if (old_x != m_xScrollPosition) {
            m_win->SetScrollPos( wxHORIZONTAL, m_xScrollPosition );
            m_targetWindow->ScrollWindow( (old_x-m_xScrollPosition)*m_xScrollPixelsPerLine, 0,
                                          GetScrollRect() );
        }
    }
    if ((y_pos != -1) && (m_yScrollPixelsPerLine))
    {
        int old_y = m_yScrollPosition;
        m_yScrollPosition = y_pos;

        // Calculate page size i.e. number of scroll units you get on the
        // current client window
        int noPagePositions = (int) ( (h/(double)m_yScrollPixelsPerLine) + 0.5 );
        if (noPagePositions < 1) noPagePositions = 1;

        // Correct position if greater than extent of canvas minus
        // the visible portion of it or if below zero
        m_yScrollPosition = wxMin( m_yScrollLines-noPagePositions, m_yScrollPosition );
        m_yScrollPosition = wxMax( 0, m_yScrollPosition );

        if (old_y != m_yScrollPosition) {
            m_win->SetScrollPos( wxVERTICAL, m_yScrollPosition );
            m_targetWindow->ScrollWindow( 0, (old_y-m_yScrollPosition)*m_yScrollPixelsPerLine,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?