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 + -
显示快捷键?