Files
wxWidgets/src/generic/scrolwin.cpp
Robert Roebling d4c99d6fa8 Pretty redical change concerning the underlying
X's windows' position. Even without having
  scrolled anywhere, the device origin of the
  top left corner is no longer certain to be
  zero,zero.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@401 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
1998-07-30 09:16:21 +00:00

445 lines
11 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: scrolwin.cpp
// Purpose: wxScrolledWindow implementation
// Author: Julian Smart
// Modified by:
// Created: 01/02/97
// RCS-ID: $Id$
// Copyright: (c) Julian Smart and Markus Holzem
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
#pragma implementation
#pragma implementation "scrolwin.h"
#endif
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#include "wx/utils.h"
#include "wx/dcclient.h"
#ifdef __WXMSW__
#include "windows.h"
#endif
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#include "wx/generic/scrolwin.h"
#if !USE_SHARED_LIBRARY
BEGIN_EVENT_TABLE(wxScrolledWindow, wxWindow)
EVT_SCROLL(wxScrolledWindow::OnScroll)
EVT_SIZE(wxScrolledWindow::OnSize)
EVT_PAINT(wxScrolledWindow::OnPaint)
END_EVENT_TABLE()
IMPLEMENT_DYNAMIC_CLASS(wxScrolledWindow, wxWindow)
#endif
wxScrolledWindow::wxScrolledWindow(void)
{
m_xScrollPixelsPerLine = 0;
m_yScrollPixelsPerLine = 0;
m_xScrollingEnabled = TRUE;
m_yScrollingEnabled = TRUE;
m_xScrollPosition = 0;
m_yScrollPosition = 0;
m_xScrollLines = 0;
m_yScrollLines = 0;
m_xScrollLinesPerPage = 0;
m_yScrollLinesPerPage = 0;
}
bool wxScrolledWindow::Create(wxWindow *parent, wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name)
{
m_xScrollPixelsPerLine = 0;
m_yScrollPixelsPerLine = 0;
m_xScrollingEnabled = TRUE;
m_yScrollingEnabled = TRUE;
m_xScrollPosition = 0;
m_yScrollPosition = 0;
m_xScrollLines = 0;
m_yScrollLines = 0;
m_xScrollLinesPerPage = 0;
m_yScrollLinesPerPage = 0;
return wxWindow::Create(parent, id, pos, size, style, name);
}
/*
* pixelsPerUnitX/pixelsPerUnitY: number of pixels per unit (e.g. pixels per text line)
* noUnitsX/noUnitsY: : no. units per scrollbar
*/
void wxScrolledWindow::SetScrollbars (int pixelsPerUnitX, int pixelsPerUnitY,
int noUnitsX, int noUnitsY,
int xPos, int yPos, bool noRefresh )
{
bool do_refresh =
(
(noUnitsX != 0 && m_xScrollLines == 0) ||
(noUnitsX < m_xScrollPosition) ||
(noUnitsY != 0 && m_yScrollLines == 0) ||
(noUnitsY < m_yScrollPosition) ||
(xPos != m_xScrollPosition) ||
(yPos != m_yScrollPosition) ||
(pixelsPerUnitX != m_xScrollPixelsPerLine) ||
(pixelsPerUnitY != m_yScrollPixelsPerLine)
);
m_xScrollPixelsPerLine = pixelsPerUnitX;
m_yScrollPixelsPerLine = pixelsPerUnitY;
m_xScrollPosition = xPos;
m_yScrollPosition = yPos;
m_xScrollLines = noUnitsX;
m_yScrollLines = noUnitsY;
AdjustScrollbars();
if (do_refresh && !noRefresh) Refresh();
#ifdef __WXMSW__
UpdateWindow ((HWND) GetHWND());
#endif
}
void wxScrolledWindow::OnScroll(wxScrollEvent& event)
{
int orient = event.GetOrientation();
int nScrollInc = CalcScrollInc(event);
if (nScrollInc == 0)
return;
// TODO: should we store the scroll position here as well as in wxWindow?
if (orient == wxHORIZONTAL)
{
int newPos = m_xScrollPosition + nScrollInc;
SetScrollPos(wxHORIZONTAL, newPos, TRUE );
}
else
{
int newPos = m_yScrollPosition + nScrollInc;
SetScrollPos(wxVERTICAL, newPos, TRUE );
}
/*
// TODO We need to multiply the ScrollWindow amount by the scaling
// factor, but how do we know what this is in wxWin 2.0???
float scaleX = 1.0;
float scaleY = 1.0;
if ( this->IsKindOf(CLASSINFO(wxCanvas)) )
{
wxDC* dc = ((wxCanvas *)this)->GetDC();
dc->GetUserScale(&scaleX, &scaleY);
}
*/
if (orient == wxHORIZONTAL)
{
m_xScrollPosition += nScrollInc;
}
else
{
m_yScrollPosition += nScrollInc;
}
if (orient == wxHORIZONTAL)
{
if (m_xScrollingEnabled)
ScrollWindow(-m_xScrollPixelsPerLine * nScrollInc, 0, NULL);
else
Refresh();
}
else
{
if (m_yScrollingEnabled)
ScrollWindow(0, -m_yScrollPixelsPerLine * nScrollInc, NULL);
else
Refresh();
}
}
int wxScrolledWindow::CalcScrollInc(wxScrollEvent& event)
{
int pos = event.GetPosition();
int orient = event.GetOrientation();
int nScrollInc = 0;
switch (event.GetEventType())
{
case wxEVENT_TYPE_SCROLL_TOP:
{
if (orient == wxHORIZONTAL)
nScrollInc = - m_xScrollPosition;
else
nScrollInc = - m_yScrollPosition;
break;
}
case wxEVENT_TYPE_SCROLL_BOTTOM:
{
if (orient == wxHORIZONTAL)
nScrollInc = m_xScrollLines - m_xScrollPosition;
else
nScrollInc = m_yScrollLines - m_yScrollPosition;
break;
}
case wxEVENT_TYPE_SCROLL_LINEUP:
{
nScrollInc = -1;
break;
}
case wxEVENT_TYPE_SCROLL_LINEDOWN:
{
nScrollInc = 1;
break;
}
case wxEVENT_TYPE_SCROLL_PAGEUP:
{
if (orient == wxHORIZONTAL)
nScrollInc = -GetScrollPageSize(wxHORIZONTAL);
else
nScrollInc = -GetScrollPageSize(wxVERTICAL);
break;
}
case wxEVENT_TYPE_SCROLL_PAGEDOWN:
{
if (orient == wxHORIZONTAL)
nScrollInc = GetScrollPageSize(wxHORIZONTAL);
else
nScrollInc = GetScrollPageSize(wxVERTICAL);
break;
}
case wxEVENT_TYPE_SCROLL_THUMBTRACK:
{
if (orient == wxHORIZONTAL)
nScrollInc = pos - m_xScrollPosition;
else
nScrollInc = pos - m_yScrollPosition;
break;
}
default:
{
break;
}
}
if (orient == wxHORIZONTAL)
{
int w, h;
GetClientSize(&w, &h);
int nMaxWidth = m_xScrollLines*m_xScrollPixelsPerLine;
int noPositions = (int) ( ((nMaxWidth - w)/(float)m_xScrollPixelsPerLine) + 0.5 );
if (noPositions < 0)
noPositions = 0;
if ( (m_xScrollPosition + nScrollInc) < 0 )
nScrollInc = -m_xScrollPosition; // As -ve as we can go
else if ( (m_xScrollPosition + nScrollInc) > noPositions )
nScrollInc = noPositions - m_xScrollPosition; // As +ve as we can go
return nScrollInc;
}
else
{
int w, h;
GetClientSize(&w, &h);
int nMaxHeight = m_yScrollLines*m_yScrollPixelsPerLine;
int noPositions = (int) ( ((nMaxHeight - h)/(float)m_yScrollPixelsPerLine) + 0.5 );
if (noPositions < 0)
noPositions = 0;
if ( (m_yScrollPosition + nScrollInc) < 0 )
nScrollInc = -m_yScrollPosition; // As -ve as we can go
else if ( (m_yScrollPosition + nScrollInc) > noPositions )
nScrollInc = noPositions - m_yScrollPosition; // As +ve as we can go
return nScrollInc;
}
}
// Adjust the scrollbars - new version.
void wxScrolledWindow::AdjustScrollbars(void)
{
int w, h;
GetClientSize(&w, &h);
// Recalculate scroll bar range and position
if (m_xScrollLines > 0)
{
int nMaxWidth = m_xScrollLines*m_xScrollPixelsPerLine;
int newRange = (int) ( ((nMaxWidth)/(float)m_xScrollPixelsPerLine) + 0.5 );
if (newRange < 0)
newRange = 0;
m_xScrollPosition = wxMin(newRange, m_xScrollPosition);
// Calculate page size i.e. number of scroll units you get on the
// current client window
int noPagePositions = (int) ( (w/(float)m_xScrollPixelsPerLine) + 0.5 );
if (noPagePositions < 1)
noPagePositions = 1;
SetScrollbar(wxHORIZONTAL, m_xScrollPosition, noPagePositions, newRange);
SetScrollPageSize(wxHORIZONTAL, noPagePositions);
}
// Robert Roebling
else
{
m_xScrollPosition = 0;
SetScrollbar (wxHORIZONTAL, 0, 0, 0, FALSE);
}
if (m_yScrollLines > 0)
{
int nMaxHeight = m_yScrollLines*m_yScrollPixelsPerLine;
int newRange = (int) ( ((nMaxHeight)/(float)m_yScrollPixelsPerLine) + 0.5 );
if (newRange < 0)
newRange = 0;
m_yScrollPosition = wxMin(newRange, m_yScrollPosition);
// Calculate page size i.e. number of scroll units you get on the
// current client window
int noPagePositions = (int) ( (h/(float)m_yScrollPixelsPerLine) + 0.5 );
if (noPagePositions < 1)
noPagePositions = 1;
SetScrollbar(wxVERTICAL, m_yScrollPosition, noPagePositions, newRange);
SetScrollPageSize(wxVERTICAL, noPagePositions);
}
else
{
m_yScrollPosition = 0;
SetScrollbar (wxVERTICAL, 0, 0, 0, FALSE); // Robert Roebling
}
}
// Default OnSize resets scrollbars, if any
void wxScrolledWindow::OnSize(wxSizeEvent& WXUNUSED(event))
{
#if USE_CONSTRAINTS
if (GetAutoLayout())
Layout();
#endif
AdjustScrollbars();
}
// This calls OnDraw, having adjusted the origin according to the current
// scroll position
void wxScrolledWindow::OnPaint(wxPaintEvent& WXUNUSED(event))
{
wxPaintDC dc(this);
PrepareDC(dc);
OnDraw(dc);
}
// Override this function if you don't want to have wxScrolledWindow
// automatically change the origin according to the scroll position.
void wxScrolledWindow::PrepareDC(wxDC& dc)
{
dc.SetDeviceOrigin(- m_xScrollPosition * m_xScrollPixelsPerLine, - m_yScrollPosition * m_yScrollPixelsPerLine);
}
#if WXWIN_COMPATIBILITY
void wxScrolledWindow::GetScrollUnitsPerPage (int *x_page, int *y_page) const
{
*x_page = GetScrollPageSize(wxHORIZONTAL);
*y_page = GetScrollPageSize(wxVERTICAL);
}
#endif
void wxScrolledWindow::GetScrollPixelsPerUnit (int *x_unit, int *y_unit) const
{
*x_unit = m_xScrollPixelsPerLine;
*y_unit = m_yScrollPixelsPerLine;
}
int wxScrolledWindow::GetScrollPageSize(int orient) const
{
if ( orient == wxHORIZONTAL )
return m_xScrollLinesPerPage;
else
return m_yScrollLinesPerPage;
}
void wxScrolledWindow::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 wxScrolledWindow::Scroll (int x_pos, int y_pos)
{
int old_x, old_y;
ViewStart (&old_x, &old_y);
if (((x_pos == -1) || (x_pos == old_x)) && ((y_pos == -1) || (y_pos == old_y)))
return;
if (x_pos > -1)
{
m_xScrollPosition = x_pos;
SetScrollPos (wxHORIZONTAL, x_pos, TRUE);
}
if (y_pos > -1)
{
m_yScrollPosition = y_pos;
SetScrollPos (wxVERTICAL, y_pos, TRUE);
}
Refresh();
#ifdef __WXMSW__
::UpdateWindow ((HWND) GetHWND());
#endif
}
void wxScrolledWindow::EnableScrolling (bool x_scroll, bool y_scroll)
{
m_xScrollingEnabled = x_scroll;
m_yScrollingEnabled = y_scroll;
}
void wxScrolledWindow::GetVirtualSize (int *x, int *y) const
{
*x = m_xScrollPixelsPerLine * m_xScrollLines;
*y = m_yScrollPixelsPerLine * m_yScrollLines;
}
// Where the current view starts from
void wxScrolledWindow::ViewStart (int *x, int *y) const
{
*x = m_xScrollPosition;
*y = m_yScrollPosition;
}
void wxScrolledWindow::CalcScrolledPosition(int x, int y, int *xx, int *yy) const
{
*xx = x - m_xScrollPosition * m_xScrollPixelsPerLine;
*yy = y - m_yScrollPosition * m_yScrollPixelsPerLine;
}
void wxScrolledWindow::CalcUnscrolledPosition(int x, int y, float *xx, float *yy) const
{
*xx = (float)(x + m_xScrollPosition * m_xScrollPixelsPerLine);
*yy = (float)(y + m_yScrollPosition * m_yScrollPixelsPerLine);
}