// headers
// ----------------------------------------------------------------------------
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
-#pragma implementation "vscroll.h"
-#endif
-
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#pragma hdrstop
#endif
+#ifndef WX_PRECOMP
+ #include "wx/sizer.h"
+#endif
+
#include "wx/vscroll.h"
// ----------------------------------------------------------------------------
BEGIN_EVENT_TABLE(wxVScrolledWindow, wxPanel)
EVT_SIZE(wxVScrolledWindow::OnSize)
EVT_SCROLLWIN(wxVScrolledWindow::OnScroll)
+#if wxUSE_MOUSEWHEEL
+ EVT_MOUSEWHEEL(wxVScrolledWindow::OnMouseWheel)
+#endif
END_EVENT_TABLE()
m_nVisible = 1;
m_heightTotal = 0;
+
+#if wxUSE_MOUSEWHEEL
+ m_sumWheelRotation = 0;
+#endif
}
// ----------------------------------------------------------------------------
return lineFirst;
}
+void wxVScrolledWindow::RemoveScrollbar()
+{
+ m_lineFirst = 0;
+ m_nVisible = m_lineMax;
+ SetScrollbar(wxVERTICAL, 0, 0, 0);
+}
+
void wxVScrolledWindow::UpdateScrollbar()
{
// see how many lines can we fit on screen
h += OnGetLineHeight(line);
}
+ // if we still have remaining space below, maybe we can fit everything?
+ if ( h < hWindow )
+ {
+ wxCoord hAll = h;
+ for ( size_t lineFirst = m_lineFirst; lineFirst > 0; lineFirst-- )
+ {
+ hAll += OnGetLineHeight(m_lineFirst - 1);
+ if ( hAll > hWindow )
+ break;
+ }
+
+ if ( hAll < hWindow )
+ {
+ // we don't need scrollbar at all
+ RemoveScrollbar();
+ return;
+ }
+ }
+
m_nVisible = line - m_lineFirst;
int pageSize = m_nVisible;
m_heightTotal = EstimateTotalHeight();
// recalculate the scrollbars parameters
- m_lineFirst = 1; // make sure it is != 0
- ScrollToLine(0);
+ if ( count )
+ {
+ m_lineFirst = 1; // make sure it is != 0
+ ScrollToLine(0);
+ }
+ else // no items
+ {
+ RemoveScrollbar();
+ }
}
void wxVScrolledWindow::RefreshLine(size_t line)
wxRect rect;
rect.width = GetClientSize().x;
rect.height = OnGetLineHeight(line);
- for ( size_t n = GetFirstVisibleLine(); n < line; n++ )
+ for ( size_t n = GetVisibleBegin(); n < line; n++ )
{
rect.y += OnGetLineHeight(n);
}
// clump the range to just the visible lines -- it is useless to refresh
// the other ones
- if ( from < GetFirstVisibleLine() )
- from = GetFirstVisibleLine();
+ if ( from < GetVisibleBegin() )
+ from = GetVisibleBegin();
- if ( to > GetLastVisibleLine() )
- to = GetLastVisibleLine();
+ if ( to >= GetVisibleEnd() )
+ to = GetVisibleEnd();
+ else
+ to++;
// calculate the rect occupied by these lines on screen
wxRect rect;
rect.width = GetClientSize().x;
- for ( size_t nBefore = GetFirstVisibleLine(); nBefore < from; nBefore++ )
+ for ( size_t nBefore = GetVisibleBegin(); nBefore < from; nBefore++ )
{
rect.y += OnGetLineHeight(nBefore);
}
- for ( size_t nBetween = from; nBetween <= to; nBetween++ )
+ for ( size_t nBetween = from; nBetween < to; nBetween++ )
{
rect.height += OnGetLineHeight(nBetween);
}
Refresh();
}
+bool wxVScrolledWindow::Layout()
+{
+ if ( GetSizer() )
+ {
+ // adjust the sizer dimensions/position taking into account the
+ // virtual size and scrolled position of the window.
+
+ int w, h;
+ GetVirtualSize(&w, &h);
+
+ // x is always 0 so no variable needed
+ int y = -GetLinesHeight(0, GetFirstVisibleLine());
+
+ GetSizer()->SetDimension(0, y, w, h);
+ return true;
+ }
+
+ // fall back to default for LayoutConstraints
+ return wxPanel::Layout();
+}
+
int wxVScrolledWindow::HitTest(wxCoord WXUNUSED(x), wxCoord y) const
{
- const size_t lineMax = GetLastVisibleLine();
- for ( size_t line = GetFirstVisibleLine(); line <= lineMax; line++ )
+ const size_t lineMax = GetVisibleEnd();
+ for ( size_t line = GetVisibleBegin(); line < lineMax; line++ )
{
y -= OnGetLineHeight(line);
if ( y < 0 )
// remember the currently shown lines for the refresh code below
- size_t lineFirstOld = GetFirstVisibleLine(),
- lineLastOld = GetLastVisibleLine();
+ size_t lineFirstOld = GetVisibleBegin(),
+ lineLastOld = GetVisibleEnd();
m_lineFirst = line;
// finally refresh the display -- but only redraw as few lines as possible
// to avoid flicker
- if ( GetFirstVisibleLine() > lineLastOld ||
- GetLastVisibleLine() < lineFirstOld )
+ if ( GetVisibleBegin() >= lineLastOld ||
+ GetVisibleEnd() <= lineFirstOld )
{
// the simplest case: we don't have any old lines left, just redraw
// everything
}
else // overlap between the lines we showed before and should show now
{
- ScrollWindow(0, GetLinesHeight(GetFirstVisibleLine(), lineFirstOld));
+ ScrollWindow(0, GetLinesHeight(GetVisibleBegin(), lineFirstOld));
}
return true;
int line;
if ( pages > 0 )
{
- line = GetLastVisibleLine();
+ line = GetVisibleEnd();
+ if ( line )
+ line--;
pages--;
}
else // pages < 0
{
- line = FindFirstFromBottom(GetFirstVisibleLine());
+ line = FindFirstFromBottom(GetVisibleBegin());
pages++;
}
}
else if ( evtType == wxEVT_SCROLLWIN_PAGEDOWN )
{
- lineFirstNew = GetLastVisibleLine();
+ lineFirstNew = GetVisibleEnd();
+ if ( lineFirstNew )
+ lineFirstNew--;
}
else if ( evtType == wxEVT_SCROLLWIN_THUMBRELEASE )
{
{
lineFirstNew = event.GetPosition();
}
-
+
else // unknown scroll event?
{
wxFAIL_MSG( _T("unknown scroll event type?") );
#endif // __WXMAC__
}
+#if wxUSE_MOUSEWHEEL
+
+void wxVScrolledWindow::OnMouseWheel(wxMouseEvent& event)
+{
+ m_sumWheelRotation += event.GetWheelRotation();
+ int delta = event.GetWheelDelta();
+
+ // how much to scroll this time
+ int units_to_scroll = -(m_sumWheelRotation/delta);
+ if ( !units_to_scroll )
+ return;
+
+ m_sumWheelRotation += units_to_scroll*delta;
+
+ if ( !event.IsPageScroll() )
+ ScrollLines( units_to_scroll*event.GetLinesPerAction() );
+ else
+ // scroll pages instead of lines
+ ScrollPages( units_to_scroll );
+}
+
+#endif // wxUSE_MOUSEWHEEL
+