1. added GetClientAreaOrigin to wxWindow, calculations everywhere use it

2. added horz scrolling to the listbox and fixed thevertical one
3. added wxALWAYS_SHOW_SB (a.k.a. wxLB_ALWAYS_SB) style
4. corrected thumb size calculations


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/wxUNIVERSAL@8248 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2000-09-03 23:55:28 +00:00
parent 4d437f4b2b
commit 8d400a3a23
19 changed files with 681 additions and 237 deletions

8
TODO Normal file
View File

@@ -0,0 +1,8 @@
All
1. extended listbox interface?
2. problem with horz scrolling: the focus rect isn't drawn entirely...
MSW
GTK

View File

@@ -880,6 +880,13 @@ enum wxBorder
// Override CTL3D or native 3D styles for children
#define wxNO_3D 0x00800000
// wxALWAYS_SHOW_SB: instead of hiding the scrollbar when it is not needed,
// disable it - but still show (see also wxLB_ALWAYS_SB style)
//
// NB: as this style is only supported by wxUniversal so far as it doesn't use
// wxUSER_COLOURS/wxNO_3D, we reuse the same style value
#define wxALWAYS_SHOW_SB 0x00800000
// Clip children when painting, which reduces flicker in e.g. frames and
// splitter windows, but can't be used in a panel where a static box must be
// 'transparent' (panel paints the background for it)

View File

@@ -90,10 +90,6 @@ public:
const wxString& strArg = wxEmptyString);
protected:
// by default static controls don't have the border and all the others do
// have it
virtual wxBorder GetDefaultBorder() const;
// create the event translator object for this control: the base class
// action creates the default one which doesn't do anything
virtual wxInputHandler *CreateInputHandler() const;

View File

@@ -223,6 +223,7 @@ protected:
wxRenderer *m_renderer;
wxWindow *m_winCapture;
int m_btnCapture;
};
#endif // _WX_UNIV_INPHAND_H_

View File

@@ -75,12 +75,9 @@ public:
virtual void Clear();
virtual void Delete(int n);
virtual int GetCount() const
{ return (int)m_strings.GetCount(); }
virtual wxString GetString(int n) const
{ return m_strings[n]; }
virtual void SetString(int n, const wxString& s)
{ m_strings[n] = s; RefreshItem(n); }
virtual int GetCount() const { return (int)m_strings.GetCount(); }
virtual wxString GetString(int n) const { return m_strings[n]; }
virtual void SetString(int n, const wxString& s);
virtual int FindString(const wxString& s) const
{ return m_strings.Index(s); }
@@ -125,10 +122,11 @@ public:
void Select(bool sel = TRUE);
void EnsureVisible();
// get, calculating it if necessary, the number of items per page and the
// height of each line
// get, calculating it if necessary, the number of items per page, the
// height of each line and the max width of an item
int GetItemsPerPage() const;
wxCoord GetLineHeight() const;
wxCoord GetMaxWidth() const;
// override the wxControl virtual methods
virtual bool PerformAction(const wxControlAction& action,
@@ -138,6 +136,7 @@ public:
protected:
virtual wxSize DoGetBestClientSize() const;
virtual void DoDraw(wxControlRenderer *renderer);
virtual wxBorder GetDefaultBorder() const;
// common part of all ctors
void Init();
@@ -160,6 +159,10 @@ protected:
// calculate the number of items per page using our current size
void CalcItemsPerPage();
// can/should we have a horz scrollbar?
bool HasHorzScrollbar() const
{ return (m_windowStyle & wxLB_HSCROLL) != 0; }
// the array containing all items (it is sorted if the listbox has
// wxLB_SORT style)
wxArrayString m_strings;
@@ -185,13 +188,16 @@ private:
// the height of one line in the listbox (all lines have the same height)
wxCoord m_lineHeight;
// the maximal width of a listbox item
wxCoord m_maxWidth;
// the number of items per page
size_t m_itemsPerPage;
// if the number of items has changed we may need to show/hide the
// scrollbar
bool m_updateScrollbar,
m_showScrollbar;
bool m_updateScrollbarX, m_updateScrollbarY,
m_showScrollbarX, m_showScrollbarY;
// if the current item has changed, we might need to scroll if it went out
// of the window

View File

@@ -135,6 +135,10 @@ public:
const wxRect& rect,
int flags = 0) = 0;
// draw the rectangle in the corner between two scrollbars
virtual void DrawScrollCorner(wxDC& dc,
const wxRect& rect) = 0;
// draw an item of a wxControlWithItems
virtual void DrawItem(wxDC& dc,
const wxString& label,
@@ -144,6 +148,10 @@ public:
// geometry functions
// ------------------
// get the dimensions of the border: rect.x/y contain the width/height of
// the left/top side, width/heigh - of the right/bottom one
virtual wxRect GetBorderDimensions(wxBorder border) const = 0;
// adjust the size of the control of the given class: for most controls,
// this just takes into account the border, but for some (buttons, for
// example) it is more complicated - the result being, in any case, that
@@ -156,6 +164,9 @@ public:
wxScrollBar::Element elem,
int thumbPos = -1) const = 0;
// returns the size of the scrollbar shaft excluding the arrows
virtual wxCoord GetScrollbarSize(const wxScrollBar *scrollbar) = 0;
// returns one of wxHT_SCROLLBAR_XXX constants
virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar,
const wxPoint& pt) const = 0;
@@ -266,6 +277,9 @@ public:
const wxRect& rect,
int flags = 0)
{ m_renderer->DrawScrollbarShaft(dc, orient, rect, flags); }
virtual void DrawScrollCorner(wxDC& dc,
const wxRect& rect)
{ m_renderer->DrawScrollCorner(dc, rect); }
virtual void DrawItem(wxDC& dc,
const wxString& label,
const wxRect& rect,
@@ -274,11 +288,15 @@ public:
virtual void AdjustSize(wxSize *size, const wxWindow *window)
{ m_renderer->AdjustSize(size, window); }
virtual wxRect GetBorderDimensions(wxBorder border) const
{ m_renderer->GetBorderDimensions(border); }
virtual wxRect GetScrollbarRect(const wxScrollBar *scrollbar,
wxScrollBar::Element elem,
int thumbPos = -1) const
{ return m_renderer->GetScrollbarRect(scrollbar, elem, thumbPos); }
virtual wxCoord GetScrollbarSize(const wxScrollBar *scrollbar)
{ return m_renderer->GetScrollbarSize(scrollbar); }
virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar,
const wxPoint& pt) const
{ return m_renderer->HitTestScrollbar(scrollbar, pt); }

View File

@@ -103,11 +103,12 @@ public:
// wxScrollBar sub elements state (combination of wxCONTROL_XXX)
void SetState(Element which, int flags);
int GetState(Element which) const { return m_elementsState[which]; }
int GetState(Element which) const;
protected:
virtual wxSize DoGetBestClientSize() const;
virtual void DoDraw(wxControlRenderer *renderer);
virtual wxBorder GetDefaultBorder() const { return wxBORDER_NONE; }
// event handler
void OnIdle(wxIdleEvent& event);

View File

@@ -64,9 +64,16 @@ public:
const wxSize& size = wxDefaultSize,
long style = 0,
const wxString& name = wxPanelNameStr)
: wxWindowNative(parent, id, pos, size, style, name)
: wxWindowNative(parent, id, pos, size, style | wxCLIP_CHILDREN, name)
{ Init(); }
bool Create(wxWindow *parent,
wxWindowID id,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = 0,
const wxString& name = wxPanelNameStr);
// background pixmap support
// -------------------------
@@ -93,6 +100,9 @@ public:
virtual void ScrollWindow(int dx, int dy,
const wxRect* rect = (wxRect *) NULL);
// take into account the borders here
virtual wxPoint GetClientAreaOrigin() const;
// miscellaneous other methods
// ---------------------------
@@ -130,6 +140,9 @@ protected:
// draw the control background, return TRUE if done
virtual bool DoDrawBackground(wxControlRenderer *renderer);
// draw the controls border
virtual void DoDrawBorder(wxControlRenderer *renderer);
// draw the controls contents
virtual void DoDraw(wxControlRenderer *renderer);

View File

@@ -259,6 +259,17 @@ public:
return wxSize(w, h);
}
// get the origin of the client area of the window relative to the
// window top left corner (the client area may be shifted because of
// the borders, scrollbars, other decorations...)
virtual wxPoint GetClientAreaOrigin() const;
// get the client rectangle in window (i.e. client) coordinates
wxRect GetClientRect() const
{
return wxRect(GetClientAreaOrigin(), GetClientSize());
}
// get the size best suited for the window (in fact, minimal
// acceptable size using which it will still look "nice")
wxSize GetBestSize() const { return DoGetBestSize(); }

View File

@@ -317,10 +317,13 @@ MyUnivFrame::MyUnivFrame(const wxString& title)
};
wxListBox *lbox = new wxListBox(this, -1, wxPoint(550, 10), wxDefaultSize,
WXSIZEOF(choices), choices,
wxLB_MULTIPLE);
for ( int i = 0; i < 20; i++ )
wxLB_MULTIPLE | wxLB_ALWAYS_SB);
lbox = new wxListBox(this, -1, wxPoint(550, 300), wxDefaultSize,
0, NULL, wxLB_HSCROLL);
for ( int i = 1; i <= 20; i++ )
{
lbox->Append(wxString::Format(_T("entry %d"), i));
lbox->Append(wxString::Format(_T("%sentry %d"),
i % 10 ? _T("") : _T("very very long "), i));
}
}

View File

@@ -391,7 +391,11 @@ void wxWindowBase::Fit()
{
if ( GetChildren().GetCount() > 0 )
{
SetClientSize(DoGetBestSize());
// leave a margin for compatibility with old version
wxSize size = DoGetBestSize();
size.x += 7;
size.y += 14;
SetClientSize(size);
}
//else: do nothing if we have no children
}
@@ -439,8 +443,7 @@ wxSize wxWindowBase::DoGetBestSize() const
maxY = wy + wh;
}
// leave a margin
return wxSize(maxX + 7, maxY + 14);
return wxSize(maxX, maxY);
}
else
{
@@ -450,6 +453,12 @@ wxSize wxWindowBase::DoGetBestSize() const
}
}
// by default the origin is not shifted
wxPoint wxWindowBase::GetClientAreaOrigin() const
{
return wxPoint(0, 0);
}
// set the min/max size of the window
void wxWindowBase::SetSizeHints(int minW, int minH,
int maxW, int maxH,

View File

@@ -419,6 +419,8 @@ void wxScrollHelper::AdjustScrollbars()
// current client window
int noPagePositions = (int) ( (w/(double)m_xScrollPixelsPerLine) + 0.5 );
if (noPagePositions < 1) noPagePositions = 1;
if ( noPagePositions > m_xScrollLines )
noPagePositions = m_xScrollLines;
// Correct position if greater than extent of canvas minus
// the visible portion of it or if below zero
@@ -441,6 +443,8 @@ void wxScrollHelper::AdjustScrollbars()
// current client window
int noPagePositions = (int) ( (h/(double)m_yScrollPixelsPerLine) + 0.5 );
if (noPagePositions < 1) noPagePositions = 1;
if ( noPagePositions > m_yScrollLines )
noPagePositions = m_yScrollLines;
// Correct position if greater than extent of canvas minus
// the visible portion of it or if below zero

View File

@@ -77,7 +77,6 @@ bool wxControl::Create(wxWindow *parent,
if ( !wxControlBase::Create(parent, id, pos, size, style, validator, name) )
return FALSE;
m_renderer = wxTheme::Get()->GetRenderer();
m_handler = CreateInputHandler();
SetBackgroundColour(parent->GetBackgroundColour());
@@ -193,13 +192,4 @@ bool wxControl::PerformAction(const wxControlAction& action,
return FALSE;
}
// ----------------------------------------------------------------------------
// border
// ----------------------------------------------------------------------------
wxBorder wxControl::GetDefaultBorder() const
{
return AcceptsFocus() ? wxBORDER_SUNKEN : wxBORDER_NONE;
}
#endif // wxUSE_CONTROLS

View File

@@ -62,6 +62,7 @@ void wxListBox::Init()
// will be calculated later when needed
m_lineHeight = 0;
m_itemsPerPage = 0;
m_maxWidth = 0;
// no items hence no current item
m_current = -1;
@@ -69,8 +70,12 @@ void wxListBox::Init()
// no need to update anything initially
m_updateCount = 0;
m_updateScrollbar =
m_showScrollbar = FALSE;
// no scrollbars to show nor update
m_updateScrollbarX =
m_showScrollbarX =
m_updateScrollbarY =
m_showScrollbarY = FALSE;
}
bool wxListBox::Create(wxWindow *parent,
@@ -83,6 +88,11 @@ bool wxListBox::Create(wxWindow *parent,
const wxValidator& validator,
const wxString &name)
{
// for compatibility accept both the new and old styles - they mean the
// same thing for us
if ( style & wxLB_ALWAYS_SB )
style |= wxALWAYS_SHOW_SB;
if ( !wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name) )
return FALSE;
@@ -113,7 +123,20 @@ int wxListBox::DoAppend(const wxString& item)
size_t index = m_strings.Add(item);
m_clientData.Insert(NULL, index);
m_updateScrollbar = TRUE;
m_updateScrollbarY = TRUE;
if ( HasHorzScrollbar() )
{
// has the max width increased?
wxClientDC dc(this);
wxCoord width;
dc.GetTextExtent(item, &width, NULL);
if ( width > m_maxWidth )
{
m_maxWidth = width;
m_updateScrollbarX = TRUE;
}
}
RefreshItem(m_strings.GetCount() - 1);
@@ -133,7 +156,14 @@ void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
m_clientData.Insert(NULL, pos + n);
}
m_updateScrollbar = TRUE;
// the number of items has changed
m_updateScrollbarY = TRUE;
// the max width also might have changed - just recalculate it instead of
// keeping track of it here, this is probably more efficient for a typical
// use pattern
m_maxWidth = 0;
m_updateScrollbarX = TRUE;
RefreshItems(pos, count);
}
@@ -143,6 +173,9 @@ void wxListBox::DoSetItems(const wxArrayString& items, void **clientData)
DoClear();
size_t count = items.GetCount();
if ( !count )
return;
m_strings.Alloc(count);
m_clientData.Alloc(count);
for ( size_t n = 0; n < count; n++ )
@@ -151,11 +184,46 @@ void wxListBox::DoSetItems(const wxArrayString& items, void **clientData)
m_clientData.Insert(clientData ? clientData[n] : NULL, index);
}
m_updateScrollbar = TRUE;
m_updateScrollbarY = TRUE;
RefreshAll();
}
void wxListBox::SetString(int n, const wxString& s)
{
if ( HasHorzScrollbar() )
{
// we need to update m_maxWidth as changing the string may cause the
// horz scrollbar [dis]appear
wxCoord widthOld;
GetTextExtent(m_strings[n], &widthOld, NULL);
m_strings[n] = s;
// has the max length changed?
wxCoord width;
GetTextExtent(s, &width, NULL);
// it might have increased if the new string is long
if ( width > m_maxWidth )
{
m_maxWidth = width;
m_updateScrollbarX = TRUE;
}
// or also decreased if the old string was the longest one
else if ( (width < m_maxWidth) && (widthOld == m_maxWidth) )
{
m_maxWidth = 0;
m_updateScrollbarX = TRUE;
}
}
else // no horz scrollbar
{
m_strings[n] = s;
}
RefreshItem(n);
}
// ----------------------------------------------------------------------------
// removing strings
// ----------------------------------------------------------------------------
@@ -180,7 +248,7 @@ void wxListBox::Clear()
{
DoClear();
m_updateScrollbar = TRUE;
m_updateScrollbarY = TRUE;
RefreshAll();
}
@@ -198,7 +266,7 @@ void wxListBox::Delete(int n)
m_clientData.RemoveAt(n);
m_updateScrollbar = TRUE;
m_updateScrollbarY = TRUE;
RefreshItems(n, GetCount() - n);
}
@@ -337,8 +405,8 @@ void wxListBox::RefreshItem(int n)
// add this item to the others which we have to refresh
if ( m_updateFrom < n )
{
if ( m_updateCount < n - m_updateFrom )
m_updateFrom = n - m_updateFrom;
if ( m_updateCount < n - m_updateFrom + 1 )
m_updateCount = n - m_updateFrom + 1;
}
else // n <= m_updateFrom
{
@@ -355,20 +423,51 @@ void wxListBox::RefreshAll()
void wxListBox::OnIdle(wxIdleEvent& event)
{
if ( m_updateScrollbar )
if ( m_updateScrollbarY || m_updateScrollbarX )
{
// is our height enough to show all items?
wxCoord lineHeight = GetLineHeight();
bool showScrollbar = GetCount()*lineHeight > GetClientSize().y;
if ( showScrollbar != m_showScrollbar )
{
// TODO: support for horz scrollbar
SetScrollbars(0, lineHeight, 0, GetCount());
wxSize size = GetClientSize();
m_showScrollbar = showScrollbar;
// is our height enough to show all items?
int nLines = GetCount();
wxCoord lineHeight = GetLineHeight();
bool showScrollbarY = nLines*lineHeight > size.y;
// check the width too if required
wxCoord charWidth, maxWidth;
bool showScrollbarX;
if ( HasHorzScrollbar() )
{
charWidth = GetCharWidth();
maxWidth = GetMaxWidth();
showScrollbarX = maxWidth > size.x;
}
else // never show it
{
charWidth = maxWidth = 0;
showScrollbarX = FALSE;
}
m_updateScrollbar = FALSE;
// reset scrollbars if something changed
if ( (showScrollbarY != m_showScrollbarY) ||
(showScrollbarX != m_showScrollbarX) )
{
int x, y;
GetViewStart(&x, &y);
SetScrollbars(charWidth, lineHeight,
showScrollbarX
? (maxWidth + 2*charWidth - 1) / charWidth
: 0,
showScrollbarY
? nLines
: 0,
x, y);
m_showScrollbarX = showScrollbarX;
m_showScrollbarY = showScrollbarY;
}
m_updateScrollbarX = FALSE;
m_updateScrollbarY = FALSE;
}
if ( m_currentChanged )
@@ -390,14 +489,13 @@ void wxListBox::OnIdle(wxIdleEvent& event)
}
else
{
wxRect rect;
rect.x = 0;
rect.y = m_updateFrom*GetLineHeight();
rect.width = 32767; // larger than our size
wxRect rect = GetClientRect();
rect.y += m_updateFrom*GetLineHeight();
rect.height = m_updateCount*GetLineHeight();
CalcScrolledPosition(rect.x, rect.y, &rect.x, &rect.y);
wxLogTrace(_T("listbox"), _T("Refreshing items %d..%d (%d-%d)"),
m_updateFrom, m_updateFrom + m_updateCount,
m_updateFrom, m_updateFrom + m_updateCount - 1,
rect.GetTop(), rect.GetBottom());
Refresh(TRUE, &rect);
@@ -411,10 +509,16 @@ void wxListBox::OnIdle(wxIdleEvent& event)
// drawing
// ----------------------------------------------------------------------------
wxBorder wxListBox::GetDefaultBorder() const
{
return wxBORDER_SUNKEN;
}
void wxListBox::DoDraw(wxControlRenderer *renderer)
{
#if 0
// draw the border first
if ( m_showScrollbar )
if ( m_showScrollbarY )
{
// we need to draw a border around the client area
renderer->GetRect().width -= GetScrollbar(wxVERTICAL)->GetSize().x;
@@ -422,21 +526,25 @@ void wxListBox::DoDraw(wxControlRenderer *renderer)
// the base class version does it for us
wxControl::DoDraw(renderer);
#endif
// adjust the DC to account for scrolling
wxDC& dc = renderer->GetDC();
PrepareDC(dc);
// get the items which must be redrawn
#if 0
int y;
GetViewStart(NULL, &y);
#if 1
wxCoord lineHeight = GetLineHeight();
wxRegion rgnUpdate = GetUpdateRegion();
rgnUpdate.Intersect(GetClientRect());
//dc.SetClippingRegion(rgnUpdate);
wxRect rectUpdate = rgnUpdate.GetBox();
size_t itemFirst = rectUpdate.GetTop() / lineHeight,
itemLast = (rectUpdate.GetBottom() + lineHeight - 1) / lineHeight,
int yTop, yBottom;
CalcUnscrolledPosition(0, rectUpdate.GetTop(), NULL, &yTop);
CalcUnscrolledPosition(0, rectUpdate.GetBottom(), NULL, &yBottom);
size_t itemFirst = yTop / lineHeight,
itemLast = (yBottom + lineHeight - 1) / lineHeight,
itemMax = m_strings.GetCount();
if ( itemFirst >= itemMax )
@@ -499,6 +607,25 @@ wxCoord wxListBox::GetLineHeight() const
return m_lineHeight;
}
wxCoord wxListBox::GetMaxWidth() const
{
if ( m_maxWidth == -1 )
{
wxCoord width;
size_t count = m_strings.GetCount();
for ( size_t n =0; n < count; n++ )
{
GetTextExtent(m_strings[n], &width, NULL);
if ( width > m_maxWidth )
{
wxConstCast(this, wxListBox)->m_maxWidth = width;
}
}
}
return m_maxWidth;
}
void wxListBox::OnSize(wxSizeEvent& event)
{
// recalculate the number of items per page
@@ -509,7 +636,7 @@ void wxListBox::OnSize(wxSizeEvent& event)
void wxListBox::DoSetFirstItem(int n)
{
wxFAIL_MSG( _T("TODO") );
SetCurrentItem(n);
}
wxSize wxListBox::DoGetBestClientSize() const
@@ -582,7 +709,7 @@ void wxListBox::SetCurrentItem(int n)
if ( n != m_current )
{
if ( m_current != -1 )
RefreshItem(n);
RefreshItem(m_current);
m_current = n;
@@ -605,7 +732,7 @@ void wxListBox::SetCurrentItem(int n)
void wxListBox::EnsureVisible()
{
if ( !m_showScrollbar )
if ( !m_showScrollbarY )
{
// nothing to do - everything is shown anyhow
return;
@@ -720,6 +847,7 @@ wxStdListboxInputHandler::wxStdListboxInputHandler(wxInputHandler *handler)
: wxStdInputHandler(handler)
{
m_winCapture = NULL;
m_btnCapture = 0;
}
int wxStdListboxInputHandler::HitTest(const wxListBox *lbox,
@@ -736,8 +864,8 @@ bool wxStdListboxInputHandler::HandleKey(wxControl *control,
const wxKeyEvent& event,
bool pressed)
{
// we're only interested in the key presses
if ( pressed )
// we're only interested in the (normal) key presses
if ( pressed && !event.AltDown() )
{
wxControlAction action;
switch ( event.GetKeyCode() )
@@ -773,18 +901,32 @@ bool wxStdListboxInputHandler::HandleMouse(wxControl *control,
// mouse events: for both of them clicking the item selects or toggles it,
// but multiple selection listboxes are different: the item is focused
// when clicked and only toggled when the button is released
if ( ((control->GetWindowStyle() & wxLB_MULTIPLE) && event.ButtonUp())
|| event.ButtonDown() || event.LeftDClick() )
if ( (m_btnCapture &&
(control->GetWindowStyle() & wxLB_MULTIPLE) &&
event.ButtonUp(m_btnCapture))
|| event.ButtonDown()
|| event.LeftDClick() )
{
wxListBox *lbox = wxStaticCast(control, wxListBox);
int item = HitTest(lbox, event);
if ( item != -1 )
{
wxControlAction action;
if ( event.ButtonUp() )
if ( m_btnCapture && event.ButtonUp(m_btnCapture) )
{
m_winCapture->ReleaseMouse();
m_winCapture = NULL;
if ( m_winCapture )
{
m_winCapture->ReleaseMouse();
m_winCapture = NULL;
m_btnCapture = 0;
}
else
{
// this is not supposed to happen - if we get here, the
// even is from the mouse button which had been pressed
// before and we must have captured the mouse back then
wxFAIL_MSG(_T("logic error in listbox mosue handling"));
}
action = wxACTION_LISTBOX_TOGGLE;
}
@@ -797,8 +939,11 @@ bool wxStdListboxInputHandler::HandleMouse(wxControl *control,
// capture the mouse to track the selected item
m_winCapture = lbox;
m_winCapture->CaptureMouse();
action = wxACTION_LISTBOX_SETFOCUS;
m_btnCapture = event.LeftDown()
? 1
: event.RightDown()
? 3
: 2;
}
else
{
@@ -809,13 +954,19 @@ bool wxStdListboxInputHandler::HandleMouse(wxControl *control,
{
action = wxACTION_LISTBOX_SELECT;
}
// in any case, clicking an item makes it the current one
lbox->PerformAction(wxACTION_LISTBOX_SETFOCUS, item);
}
else // event.LeftDClick()
{
action = wxACTION_LISTBOX_ACTIVATE;
}
lbox->PerformAction(action, item);
if ( !!action )
{
lbox->PerformAction(action, item);
}
return TRUE;
}

View File

@@ -325,14 +325,6 @@ void wxControlRenderer::DrawBorder()
// draw outline
m_renderer->DrawBorder(m_dc, m_window->GetBorder(),
m_rect, flags, &m_rect);
// fill the inside unless we have the background bitmap as we don't want to
// overwrite it
if ( !m_window->GetBackgroundBitmap().Ok() )
{
m_renderer->DrawBackground(m_dc, m_window->GetBackgroundColour(),
m_rect, flags);
}
}
void wxControlRenderer::DrawLabel(const wxBitmap& bitmap,
@@ -398,12 +390,19 @@ void wxControlRenderer::DrawBitmap(const wxBitmap& bitmap)
void wxControlRenderer::DrawBackgroundBitmap()
{
// get the bitmap and the flags
int alignment;
wxStretch stretch;
wxBitmap bmp = m_window->GetBackgroundBitmap(&alignment, &stretch);
DrawBitmap(bmp, m_rect, alignment, stretch);
if ( m_window->GetBackgroundBitmap().Ok() )
{
// get the bitmap and the flags
int alignment;
wxStretch stretch;
wxBitmap bmp = m_window->GetBackgroundBitmap(&alignment, &stretch);
DrawBitmap(bmp, m_rect, alignment, stretch);
}
else // just fill it with bg colour if no bitmap
{
m_renderer->DrawBackground(m_dc, m_window->GetBackgroundColour(),
m_rect, m_window->GetStateFlags());
}
}
void wxControlRenderer::DrawBitmap(const wxBitmap& bitmap,
@@ -549,7 +548,7 @@ void wxControlRenderer::DrawScrollbar(const wxScrollBar *scrollbar,
// and the thumb
wxScrollBar::Element elem = wxScrollBar::Element_Thumb;
wxRect rectThumb = m_renderer->GetScrollbarRect(scrollbar, elem);
if ( rgnUpdate.Contains(rectThumb) )
if ( rectThumb.width && rectThumb.height && rgnUpdate.Contains(rectThumb) )
{
wxLogTrace(_T("scroll"), _T("drawing thumb at (%d, %d)-(%d, %d)"),
rectThumb.GetLeft(),
@@ -580,13 +579,31 @@ void wxControlRenderer::DrawItems(const wxListBox *lbox,
{
// prepare for the drawing: calc the initial position
wxCoord lineHeight = lbox->GetLineHeight();
int lines, pixelsPerLine;
lbox->GetViewStart(NULL, &lines);
lbox->GetScrollPixelsPerUnit(NULL, &pixelsPerLine);
wxRect rect = m_rect;
rect.y += itemFirst*lineHeight - lines*pixelsPerLine;
// note that SetClippingRegion() needs the physical (unscrolled)
// coordinates while we use the logical (scrolled) ones for the drawing
// itself
wxRect rect = lbox->GetClientRect();
// keep the text inside the client rect or we will overwrite the vertical
// scrollbar for the long strings
m_dc.SetClippingRegion(rect.x, rect.y, rect.width + 1, rect.height + 1);
// the rect should go to the right visible border
int widthTotal;
lbox->GetVirtualSize(&widthTotal, NULL);
if ( widthTotal )
rect.width = widthTotal;
//else: no horz scrolling at all
// adjust the rect position now
lbox->CalcScrolledPosition(rect.x, rect.y, &rect.x, &rect.y);
rect.y += itemFirst*lineHeight;
rect.height = lineHeight;
// we'll keep the text colour unchanged
m_dc.SetTextForeground(lbox->GetForegroundColour());
// an item should have the focused rect only when the app has focus, so
// make sure that we never set wxCONTROL_FOCUSED flag if it doesn't
int itemCurrent = wxTheApp->IsActive() ? lbox->GetCurrentItem() : -1;

View File

@@ -54,12 +54,19 @@ public:
const wxControlAction& action,
wxScrollBar *control);
void StartAutoScroll();
virtual void Notify();
protected:
void DoNotify();
private:
wxStdScrollBarInputHandler *m_handler;
wxControlAction m_action;
wxScrollBar *m_control;
bool m_skipNext;
};
// ============================================================================
@@ -101,9 +108,8 @@ bool wxScrollBar::Create(wxWindow *parent,
const wxValidator& validator,
const wxString &name)
{
// the scrollbars always have the standard border so far
// the scrollbars never have the border
style &= ~wxBORDER_MASK;
style |= wxBORDER_SUNKEN;
if ( !wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name) )
return FALSE;
@@ -221,27 +227,38 @@ void wxScrollBar::OnIdle(wxIdleEvent& event)
{
// we try to avoid redrawing the entire shaft (which might
// be quite long) if possible by only redrawing the area
// between the old and current positions of the thumb
if ( m_thumbPosOld != -1 )
// wich really changed
if ( (n == Element_Bar_1 || n == Element_Bar_2) &&
(m_thumbPosOld != -1) )
{
// the less efficient but more reliable (i.e. this will
// probably work everywhere) version: refresh the
// distance covered by thumb since the last update
#if 0
wxRect rectOld =
GetRenderer()->GetScrollbarRect(this,
(Element)n,
m_thumbPosOld);
(Element)n,
m_thumbPosOld);
if ( IsVertical() )
{
if ( n == Element_Bar_1 )
rect.SetTop(rectOld.GetBottom());
else
rect.SetBottom(rect.GetTop());
rect.SetBottom(rectOld.GetBottom());
}
else // horizontal
{
if ( n == Element_Bar_1 )
rect.SetLeft(rectOld.GetRight());
else
rect.SetRight(rect.GetLeft());
rect.SetRight(rectOld.GetRight());
}
#else // efficient version: only repaint the area occupied by
// the thumb previously - we can't do better than this
rect = GetRenderer()->GetScrollbarRect(this,
Element_Thumb,
m_thumbPosOld);
#endif // 0/1
}
Refresh(TRUE, &rect);
@@ -265,12 +282,22 @@ void wxScrollBar::DoDraw(wxControlRenderer *renderer)
}
// ----------------------------------------------------------------------------
// input processing
// state flags
// ----------------------------------------------------------------------------
int wxScrollBar::GetState(Element which) const
{
// if the entire scrollbar is disabled, all of its elements are too
int flags = m_elementsState[which];
if ( !IsEnabled() )
flags |= wxCONTROL_DISABLED;
return flags;
}
void wxScrollBar::SetState(Element which, int flags)
{
if ( (m_elementsState[which] & ~wxCONTROL_DIRTY) != (unsigned)flags )
if ( (int)(m_elementsState[which] & ~wxCONTROL_DIRTY) != flags )
{
m_elementsState[which] = flags | wxCONTROL_DIRTY;
@@ -278,6 +305,10 @@ void wxScrollBar::SetState(Element which, int flags)
}
}
// ----------------------------------------------------------------------------
// input processing
// ----------------------------------------------------------------------------
bool wxScrollBar::PerformAction(const wxControlAction& action,
long numArg,
const wxString& strArg)
@@ -389,11 +420,40 @@ wxScrollBarTimer::wxScrollBarTimer(wxStdScrollBarInputHandler *handler,
m_handler = handler;
m_action = action;
m_control = control;
m_skipNext = FALSE;
}
void wxScrollBarTimer::StartAutoScroll()
{
// start scrolling immediately
DoNotify();
// there is an initial delay before the scrollbar starts scrolling -
// implement it by ignoring the first timer expiration and only start
// scrolling from the second one
m_skipNext = TRUE;
Start(200); // FIXME: hardcoded delay
}
void wxScrollBarTimer::DoNotify()
{
m_handler->OnScrollTimer(m_control, m_action);
}
void wxScrollBarTimer::Notify()
{
m_handler->OnScrollTimer(m_control, m_action);
if ( m_skipNext )
{
// scroll normally now - reduce the delay
Start(50); // FIXME: hardcoded delay
m_skipNext = FALSE;
}
else
{
DoNotify();
}
}
// ----------------------------------------------------------------------------
@@ -603,14 +663,12 @@ bool wxStdScrollBarInputHandler::HandleMouse(wxControl *control,
// start dragging
if ( hasAction )
{
m_timerScroll = new wxScrollBarTimer(this,
action,
scrollbar);
// start scrolling immediately
m_timerScroll->Notify();
// and continue it later
m_timerScroll->Start(50); // FIXME hardcoded delay
// this slightly unreadable code is necessary because
// m_timerScroll is of class wxTimer, not wxScrollBarTimer
wxScrollBarTimer *timerScroll =
new wxScrollBarTimer(this, action, scrollbar);
m_timerScroll = timerScroll;
timerScroll->StartAutoScroll();
}
//else: no (immediate) action

View File

@@ -95,17 +95,21 @@ public:
wxOrientation orient,
const wxRect& rect,
int flags = 0);
virtual void DrawScrollCorner(wxDC& dc,
const wxRect& rect);
virtual void DrawItem(wxDC& dc,
const wxString& label,
const wxRect& rect,
int flags = 0);
virtual void AdjustSize(wxSize *size, const wxWindow *window);
virtual wxRect GetBorderDimensions(wxBorder border) const;
// hit testing for the input handlers
virtual wxRect GetScrollbarRect(const wxScrollBar *scrollbar,
wxScrollBar::Element elem,
int thumbPos = -1) const;
virtual wxCoord GetScrollbarSize(const wxScrollBar *scrollbar);
virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar,
const wxPoint& pt) const;
virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar,
@@ -547,7 +551,7 @@ void wxGTKRenderer::DrawBorder(wxDC& dc,
break;
default:
wxFAIL_MSG(_T("unknwon border type"));
wxFAIL_MSG(_T("unknown border type"));
// fall through
case wxBORDER_DEFAULT:
@@ -559,6 +563,44 @@ void wxGTKRenderer::DrawBorder(wxDC& dc,
*rectIn = rect;
}
wxRect wxGTKRenderer::GetBorderDimensions(wxBorder border) const
{
wxCoord width;
switch ( border )
{
case wxBORDER_RAISED:
case wxBORDER_SUNKEN:
width = 2;
break;
case wxBORDER_SIMPLE:
case wxBORDER_STATIC:
width = 1;
break;
case wxBORDER_DOUBLE:
width = 3;
break;
default:
wxFAIL_MSG(_T("unknown border type"));
// fall through
case wxBORDER_DEFAULT:
case wxBORDER_NONE:
width = 0;
break;
}
wxRect rect;
rect.x =
rect.y =
rect.width =
rect.height = width;
return rect;
}
// ----------------------------------------------------------------------------
// button border
// ----------------------------------------------------------------------------
@@ -1091,6 +1133,11 @@ void wxGTKRenderer::DrawScrollbarShaft(wxDC& dc,
DoDrawBackground(dc, m_scheme->Get(wxColourScheme::SCROLLBAR), rectBar);
}
void wxGTKRenderer::DrawScrollCorner(wxDC& dc, const wxRect& rect)
{
DoDrawBackground(dc, m_scheme->Get(wxColourScheme::CONTROL), rect);
}
wxRect wxGTKRenderer::GetScrollbarRect(const wxScrollBar *scrollbar,
wxScrollBar::Element elem,
int thumbPos) const
@@ -1099,6 +1146,11 @@ wxRect wxGTKRenderer::GetScrollbarRect(const wxScrollBar *scrollbar,
thumbPos, GetScrollbarArrowSize(scrollbar));
}
wxCoord wxGTKRenderer::GetScrollbarSize(const wxScrollBar *scrollbar)
{
return StandardScrollBarSize(scrollbar, GetScrollbarArrowSize(scrollbar));
}
wxHitTest wxGTKRenderer::HitTestScrollbar(const wxScrollBar *scrollbar,
const wxPoint& pt) const
{
@@ -1149,34 +1201,9 @@ void wxGTKRenderer::AdjustSize(wxSize *size, const wxWindow *window)
else
{
// take into account the border width
wxBorder border = (wxBorder)(window->GetWindowStyle() & wxBORDER_MASK);
switch ( border )
{
case wxBORDER_SUNKEN:
case wxBORDER_RAISED:
size->x += 4;
size->y += 4;
break;
case wxBORDER_SIMPLE:
case wxBORDER_STATIC:
size->x += 2;
size->y += 2;
break;
case wxBORDER_DOUBLE:
size->x += 6;
size->y += 6;
break;
default:
wxFAIL_MSG(_T("unknwon border type"));
// fall through
case wxBORDER_DEFAULT:
case wxBORDER_NONE:
break;
}
wxRect rectBorder = GetBorderDimensions(window->GetBorder());
size->x += rectBorder.x + rectBorder.width;
size->y += rectBorder.y + rectBorder.height;
}
}

View File

@@ -113,23 +113,27 @@ public:
wxOrientation orient,
const wxRect& rect,
int flags = 0);
virtual void DrawScrollCorner(wxDC& dc,
const wxRect& rect);
virtual void DrawItem(wxDC& dc,
const wxString& label,
const wxRect& rect,
int flags = 0);
virtual void AdjustSize(wxSize *size, const wxWindow *window);
virtual wxRect GetBorderDimensions(wxBorder border) const;
virtual wxRect GetScrollbarRect(const wxScrollBar *scrollbar,
wxScrollBar::Element elem,
int thumbPos = -1) const;
virtual wxCoord GetScrollbarSize(const wxScrollBar *scrollbar);
virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar,
const wxPoint& pt) const;
virtual wxCoord ScrollbarToPixel(const wxScrollBar *scrollbar,
int thumbPos = -1);
virtual int PixelToScrollbar(const wxScrollBar *scrollbar, wxCoord coord);
virtual wxCoord GetListboxItemHeight(wxCoord fontHeight)
{ return fontHeight + 2; }
{ return fontHeight; }
protected:
// common part of DrawLabel() and DrawItem()
@@ -709,7 +713,7 @@ void wxWin32Renderer::DrawBorder(wxDC& dc,
break;
default:
wxFAIL_MSG(_T("unknwon border type"));
wxFAIL_MSG(_T("unknown border type"));
// fall through
case wxBORDER_DEFAULT:
@@ -721,6 +725,44 @@ void wxWin32Renderer::DrawBorder(wxDC& dc,
*rectIn = rect;
}
wxRect wxWin32Renderer::GetBorderDimensions(wxBorder border) const
{
wxCoord width;
switch ( border )
{
case wxBORDER_RAISED:
case wxBORDER_SUNKEN:
width = 2;
break;
case wxBORDER_SIMPLE:
case wxBORDER_STATIC:
width = 1;
break;
case wxBORDER_DOUBLE:
width = 3;
break;
default:
wxFAIL_MSG(_T("unknown border type"));
// fall through
case wxBORDER_DEFAULT:
case wxBORDER_NONE:
width = 0;
break;
}
wxRect rect;
rect.x =
rect.y =
rect.width =
rect.height = width;
return rect;
}
// ----------------------------------------------------------------------------
// button border
// ----------------------------------------------------------------------------
@@ -847,29 +889,34 @@ void wxWin32Renderer::DrawFocusRect(wxDC& dc, const wxRect& rect)
#if 0
DrawRect(dc, &rect, wxPen(*wxBLACK, 0, wxDOT));
#else
// draw the pixels manually
// draw the pixels manually: note that to behave in the same manner as
// DrawRect(), we must exclude the bottom and right borders from the
// rectangle
wxCoord x1 = rect.GetLeft(),
y1 = rect.GetTop(),
x2 = rect.GetRight(),
y2 = rect.GetBottom();
dc.SetPen(wxPen(*wxBLACK, 0, wxSOLID));
//dc.SetLogicalFunction(wxXOR);
dc.SetLogicalFunction(wxINVERT);
// Windows quirk: appears to draw them like this, from right to left
// (and I don't have Hebrew windows to see what happens there :-)
for ( wxCoord x = rect.GetRight(); x >= rect.GetLeft(); x -= 2 )
{
dc.DrawPoint(x, rect.GetTop());
dc.DrawPoint(x, rect.GetBottom());
}
wxCoord z;
for ( z = x1 + 1; z < x2; z += 2 )
dc.DrawPoint(z, rect.GetTop());
wxCoord shift = rect.width % 2 ? 0 : 1;
for ( wxCoord y = rect.GetTop() + 2; y <= rect.GetBottom(); y+= 2 )
{
dc.DrawPoint(rect.GetLeft(), y - shift);
dc.DrawPoint(rect.GetRight(), y);
}
wxCoord shift = z == x2 ? 0 : 1;
for ( z = y1 + shift; z < y2; z += 2 )
dc.DrawPoint(x2, z);
if ( shift )
{
dc.DrawPoint(rect.GetLeft(), rect.GetBottom() - 1);
}
shift = z == y2 ? 0 : 1;
for ( z = x2 - shift; z > x1; z -= 2 )
dc.DrawPoint(z, y2);
shift = z == x1 ? 0 : 1;
for ( z = y2 - shift; z > y1; z -= 2 )
dc.DrawPoint(x1, z);
dc.SetLogicalFunction(wxCOPY);
#endif // 0/1
}
@@ -912,6 +959,16 @@ void wxWin32Renderer::DrawLabel(wxDC& dc,
if ( flags & wxCONTROL_FOCUSED )
{
if ( flags & wxCONTROL_PRESSED )
{
// the focus rectangle is never pressed, so undo the shift done
// above
rectText.x--;
rectText.y--;
rectText.width--;
rectText.height--;
}
DrawFocusRect(dc, rectText);
}
}
@@ -924,20 +981,21 @@ void wxWin32Renderer::DrawItem(wxDC& dc,
wxColour colFg;
if ( flags & wxCONTROL_SELECTED )
{
dc.SetBrush(wxBrush(m_scheme->Get(wxColourScheme::HIGHLIGHT), wxSOLID));
dc.SetPen(*wxTRANSPARENT_PEN);
dc.DrawRectangle(rect);
wxColour colBg = m_scheme->Get(wxColourScheme::HIGHLIGHT);
colFg = dc.GetTextForeground();
dc.SetTextForeground(m_scheme->Get(wxColourScheme::HIGHLIGHT_TEXT));
dc.SetBrush(wxBrush(colBg, wxSOLID));
dc.SetPen(wxPen(colBg, 0, wxSOLID));
dc.DrawRectangle(rect);
}
wxRect rectText = rect;
rectText.x += 2;
rectText.width -= 2;
dc.DrawLabel(label, wxNullBitmap, rectText);
if ( flags & wxCONTROL_FOCUSED )
{
dc.SetBrush(*wxTRANSPARENT_BRUSH);
DrawFocusRect(dc, rect);
}
@@ -1037,6 +1095,7 @@ void wxWin32Renderer::DrawArrowButton(wxDC& dc,
wxArrowStyle arrowStyle)
{
wxRect rect = rectAll;
DoDrawBackground(dc, m_scheme->Get(wxColourScheme::CONTROL), rect);
DrawArrowBorder(dc, &rect, arrowStyle == Arrow_Pressed);
DrawArrow(dc, rect, arrowDir, arrowStyle);
}
@@ -1061,6 +1120,11 @@ void wxWin32Renderer::DrawScrollbarShaft(wxDC& dc,
rectBar);
}
void wxWin32Renderer::DrawScrollCorner(wxDC& dc, const wxRect& rect)
{
DoDrawBackground(dc, m_scheme->Get(wxColourScheme::CONTROL), rect);
}
wxRect wxWin32Renderer::GetScrollbarRect(const wxScrollBar *scrollbar,
wxScrollBar::Element elem,
int thumbPos) const
@@ -1069,6 +1133,11 @@ wxRect wxWin32Renderer::GetScrollbarRect(const wxScrollBar *scrollbar,
thumbPos, m_sizeScrollbarArrow);
}
wxCoord wxWin32Renderer::GetScrollbarSize(const wxScrollBar *scrollbar)
{
return StandardScrollBarSize(scrollbar, m_sizeScrollbarArrow);
}
wxHitTest wxWin32Renderer::HitTestScrollbar(const wxScrollBar *scrollbar,
const wxPoint& pt) const
{
@@ -1115,34 +1184,9 @@ void wxWin32Renderer::AdjustSize(wxSize *size, const wxWindow *window)
else
{
// take into account the border width
wxBorder border = (wxBorder)(window->GetWindowStyle() & wxBORDER_MASK);
switch ( border )
{
case wxBORDER_SUNKEN:
case wxBORDER_RAISED:
size->x += 4;
size->y += 4;
break;
case wxBORDER_SIMPLE:
case wxBORDER_STATIC:
size->x += 2;
size->y += 2;
break;
case wxBORDER_DOUBLE:
size->x += 6;
size->y += 6;
break;
default:
wxFAIL_MSG(_T("unknwon border type"));
// fall through
case wxBORDER_DEFAULT:
case wxBORDER_NONE:
break;
}
wxRect rectBorder = GetBorderDimensions(window->GetBorder());
size->x += rectBorder.x + rectBorder.width;
size->y += rectBorder.y + rectBorder.height;
}
}

View File

@@ -73,7 +73,31 @@ void wxWindow::Init()
m_isCurrent = FALSE;
m_renderer = (wxRenderer *)NULL;
m_renderer = wxTheme::Get()->GetRenderer();
}
bool wxWindow::Create(wxWindow *parent,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name)
{
if ( !wxWindowNative::Create(parent, id, pos, size,
style | wxCLIP_CHILDREN, name) )
{
return FALSE;
}
// if we should always have the scrollbar, do show it
if ( GetWindowStyle() & wxALWAYS_SHOW_SB )
{
m_scrollbarVert = new wxScrollBar(this, -1,
wxDefaultPosition, wxDefaultSize,
wxSB_VERTICAL);
}
return TRUE;
}
// ----------------------------------------------------------------------------
@@ -110,13 +134,22 @@ const wxBitmap& wxWindow::GetBackgroundBitmap(int *alignment,
// the event handler executed when the window background must be painted
void wxWindow::OnErase(wxEraseEvent& event)
{
wxControlRenderer renderer(this, *event.GetDC(),
wxTheme::Get()->GetRenderer());
wxControlRenderer renderer(this, *event.GetDC(), m_renderer);
if ( !DoDrawBackground(&renderer) )
DoDrawBackground(&renderer);
// if we have both scrollbars, we also have a square in the corner between
// them which we must paint
if ( m_scrollbarVert && m_scrollbarHorz )
{
// not processed
event.Skip();
wxRect rectCorner;
wxPoint ptOrigin = GetClientAreaOrigin();
wxSize sizeClient = GetClientSize();
rectCorner.x = ptOrigin.x + m_scrollbarHorz->GetSize().x;
rectCorner.y = ptOrigin.y + m_scrollbarVert->GetSize().y;
rectCorner.width = m_scrollbarVert->GetSize().x;
rectCorner.height = m_scrollbarHorz->GetSize().y;
m_renderer->DrawScrollCorner(*event.GetDC(), rectCorner);
}
}
@@ -134,26 +167,30 @@ void wxWindow::OnPaint(wxPaintEvent& event)
wxPaintDC dc(this);
wxControlRenderer renderer(this, dc, m_renderer);
// do draw the control!
// first, draw the border
DoDrawBorder(&renderer);
// and then draw the control
DoDraw(&renderer);
}
}
bool wxWindow::DoDrawBackground(wxControlRenderer *renderer)
{
if ( !m_bitmapBg.Ok() )
return FALSE;
renderer->DrawBackgroundBitmap();
return TRUE;
}
void wxWindow::DoDraw(wxControlRenderer *renderer)
void wxWindow::DoDrawBorder(wxControlRenderer *renderer)
{
renderer->DrawBorder();
}
void wxWindow::DoDraw(wxControlRenderer *renderer)
{
}
// ----------------------------------------------------------------------------
// state flags
// ----------------------------------------------------------------------------
@@ -251,15 +288,39 @@ void wxWindow::DoSetClientSize(int width, int height)
wxWindowNative::DoSetClientSize(width, height);
}
wxPoint wxWindow::GetClientAreaOrigin() const
{
wxPoint pt = wxWindowBase::GetClientAreaOrigin();
if ( m_renderer )
pt += m_renderer->GetBorderDimensions(GetBorder()).GetPosition();
return pt;
}
void wxWindow::DoGetClientSize(int *width, int *height) const
{
wxWindowNative::DoGetClientSize(width, height);
if ( width && m_scrollbarVert )
*width -= m_scrollbarVert->GetSize().x;
wxRect rectBorder;
if ( m_renderer )
rectBorder = m_renderer->GetBorderDimensions(GetBorder());
if ( height && m_scrollbarHorz )
*height -= m_scrollbarHorz->GetSize().y;
if ( width )
{
if ( m_scrollbarVert )
*width -= m_scrollbarVert->GetSize().x;
*width -= rectBorder.x + rectBorder.width;
}
if ( height )
{
if ( m_scrollbarHorz )
*height -= m_scrollbarHorz->GetSize().y;
*height -= rectBorder.y + rectBorder.height;
}
}
// ----------------------------------------------------------------------------
@@ -270,21 +331,31 @@ void wxWindow::DoGetClientSize(int *width, int *height) const
void wxWindow::PositionScrollbars()
{
wxCoord x, y;
DoGetSize(&x, &y);
wxRect rectClient = GetClientRect();
int width = m_scrollbarVert ? m_scrollbarVert->GetSize().x : 0;
int height = m_scrollbarHorz ? m_scrollbarHorz->GetSize().y : 0;
if ( m_scrollbarVert )
m_scrollbarVert->SetSize(x - width, 0, width, y - height);
{
m_scrollbarVert->SetSize(rectClient.GetRight() - 1,
rectClient.GetTop() - 2,
width,
rectClient.GetHeight());
}
if ( m_scrollbarHorz )
m_scrollbarHorz->SetSize(0, y - height, x - width, height);
{
m_scrollbarHorz->SetSize(rectClient.GetLeft() - 2,
rectClient.GetBottom() - 1,
rectClient.GetWidth(),
height);
}
}
void wxWindow::SetScrollbar(int orient,
int pos,
int thumb,
int pageSize,
int range,
bool refresh)
{
@@ -305,19 +376,31 @@ void wxWindow::SetScrollbar(int orient,
PositionScrollbars();
}
else if ( GetWindowStyle() & wxALWAYS_SHOW_SB )
{
// we might have disabled it before
scrollbar->Enable();
}
scrollbar->SetScrollbar(pos, thumb, range, thumb, refresh);
scrollbar->SetScrollbar(pos, pageSize, range, pageSize, refresh);
}
else // no range means no scrollbar
{
if ( scrollbar )
{
delete scrollbar;
if ( orient & wxVERTICAL )
m_scrollbarVert = NULL;
if ( GetWindowStyle() & wxALWAYS_SHOW_SB )
{
scrollbar->Disable();
}
else
m_scrollbarHorz = NULL;
{
delete scrollbar;
if ( orient & wxVERTICAL )
m_scrollbarVert = NULL;
else
m_scrollbarHorz = NULL;
}
}
}
}
@@ -367,7 +450,10 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
wxLogTrace(_T("scroll"), _T("window is %dx%d, scroll by %d, %d"),
sizeTotal.x, sizeTotal.y, dx, dy);
wxPoint ptSource, ptDest;
wxPoint ptSource, ptDest, ptOrigin;
ptSource =
ptDest =
ptOrigin = GetClientAreaOrigin();
wxSize size;
size.x = sizeTotal.x - abs(dx);
size.y = sizeTotal.y - abs(dy);
@@ -386,27 +472,23 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
if ( dx < 0 )
{
// scroll to the right, move to the left
ptSource.x = -dx;
ptDest.x = 0;
ptSource.x -= dx;
}
else
{
// scroll to the left, move to the right
ptSource.x = 0;
ptDest.x = dx;
ptDest.x += dx;
}
if ( dy < 0 )
{
// scroll down, move up
ptSource.y = -dy;
ptDest.y = 0;
ptSource.y -= dy;
}
else
{
// scroll up, move down
ptSource.y = 0;
ptDest.y = dy;
ptDest.y += dy;
}
// do move
@@ -429,23 +511,23 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
// it bad?
wxRect rect;
rect.x = ptOrigin.x;
rect.y = ptOrigin.y;
if ( dx )
{
if ( dx < 0 )
{
// refresh the area along the right border
rect.x = size.x;
rect.x += size.x;
rect.width = -dx;
}
else
{
// refresh the area along the left border
rect.x = 0;
rect.width = dx;
}
rect.y = 0;
rect.height = sizeTotal.y;
wxLogTrace(_T("scroll"), _T("refreshing (%d, %d)-(%d, %d)"),
@@ -459,17 +541,15 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
if ( dy < 0 )
{
// refresh the area along the bottom border
rect.y = size.y;
rect.y += size.y;
rect.height = -dy;
}
else
{
// refresh the area along the top border
rect.y = 0;
rect.height = dy;
}
rect.x = 0;
rect.width = sizeTotal.x;
wxLogTrace(_T("scroll"), _T("refreshing (%d, %d)-(%d, %d)"),