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 // Override CTL3D or native 3D styles for children
#define wxNO_3D 0x00800000 #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 // 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 // splitter windows, but can't be used in a panel where a static box must be
// 'transparent' (panel paints the background for it) // 'transparent' (panel paints the background for it)

View File

@@ -90,10 +90,6 @@ public:
const wxString& strArg = wxEmptyString); const wxString& strArg = wxEmptyString);
protected: 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 // create the event translator object for this control: the base class
// action creates the default one which doesn't do anything // action creates the default one which doesn't do anything
virtual wxInputHandler *CreateInputHandler() const; virtual wxInputHandler *CreateInputHandler() const;

View File

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

View File

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

View File

@@ -135,6 +135,10 @@ public:
const wxRect& rect, const wxRect& rect,
int flags = 0) = 0; 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 // draw an item of a wxControlWithItems
virtual void DrawItem(wxDC& dc, virtual void DrawItem(wxDC& dc,
const wxString& label, const wxString& label,
@@ -144,6 +148,10 @@ public:
// geometry functions // 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, // 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 // this just takes into account the border, but for some (buttons, for
// example) it is more complicated - the result being, in any case, that // example) it is more complicated - the result being, in any case, that
@@ -156,6 +164,9 @@ public:
wxScrollBar::Element elem, wxScrollBar::Element elem,
int thumbPos = -1) const = 0; 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 // returns one of wxHT_SCROLLBAR_XXX constants
virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar, virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar,
const wxPoint& pt) const = 0; const wxPoint& pt) const = 0;
@@ -266,6 +277,9 @@ public:
const wxRect& rect, const wxRect& rect,
int flags = 0) int flags = 0)
{ m_renderer->DrawScrollbarShaft(dc, orient, rect, flags); } { 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, virtual void DrawItem(wxDC& dc,
const wxString& label, const wxString& label,
const wxRect& rect, const wxRect& rect,
@@ -274,11 +288,15 @@ public:
virtual void AdjustSize(wxSize *size, const wxWindow *window) virtual void AdjustSize(wxSize *size, const wxWindow *window)
{ m_renderer->AdjustSize(size, window); } { m_renderer->AdjustSize(size, window); }
virtual wxRect GetBorderDimensions(wxBorder border) const
{ m_renderer->GetBorderDimensions(border); }
virtual wxRect GetScrollbarRect(const wxScrollBar *scrollbar, virtual wxRect GetScrollbarRect(const wxScrollBar *scrollbar,
wxScrollBar::Element elem, wxScrollBar::Element elem,
int thumbPos = -1) const int thumbPos = -1) const
{ return m_renderer->GetScrollbarRect(scrollbar, elem, thumbPos); } { return m_renderer->GetScrollbarRect(scrollbar, elem, thumbPos); }
virtual wxCoord GetScrollbarSize(const wxScrollBar *scrollbar)
{ return m_renderer->GetScrollbarSize(scrollbar); }
virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar, virtual wxHitTest HitTestScrollbar(const wxScrollBar *scrollbar,
const wxPoint& pt) const const wxPoint& pt) const
{ return m_renderer->HitTestScrollbar(scrollbar, pt); } { return m_renderer->HitTestScrollbar(scrollbar, pt); }

View File

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

View File

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

View File

@@ -259,6 +259,17 @@ public:
return wxSize(w, h); 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 // get the size best suited for the window (in fact, minimal
// acceptable size using which it will still look "nice") // acceptable size using which it will still look "nice")
wxSize GetBestSize() const { return DoGetBestSize(); } 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, wxListBox *lbox = new wxListBox(this, -1, wxPoint(550, 10), wxDefaultSize,
WXSIZEOF(choices), choices, WXSIZEOF(choices), choices,
wxLB_MULTIPLE); wxLB_MULTIPLE | wxLB_ALWAYS_SB);
for ( int i = 0; i < 20; i++ ) 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 ) 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 //else: do nothing if we have no children
} }
@@ -439,8 +443,7 @@ wxSize wxWindowBase::DoGetBestSize() const
maxY = wy + wh; maxY = wy + wh;
} }
// leave a margin return wxSize(maxX, maxY);
return wxSize(maxX + 7, maxY + 14);
} }
else 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 // set the min/max size of the window
void wxWindowBase::SetSizeHints(int minW, int minH, void wxWindowBase::SetSizeHints(int minW, int minH,
int maxW, int maxH, int maxW, int maxH,

View File

@@ -419,6 +419,8 @@ void wxScrollHelper::AdjustScrollbars()
// current client window // current client window
int noPagePositions = (int) ( (w/(double)m_xScrollPixelsPerLine) + 0.5 ); int noPagePositions = (int) ( (w/(double)m_xScrollPixelsPerLine) + 0.5 );
if (noPagePositions < 1) noPagePositions = 1; if (noPagePositions < 1) noPagePositions = 1;
if ( noPagePositions > m_xScrollLines )
noPagePositions = m_xScrollLines;
// Correct position if greater than extent of canvas minus // Correct position if greater than extent of canvas minus
// the visible portion of it or if below zero // the visible portion of it or if below zero
@@ -441,6 +443,8 @@ void wxScrollHelper::AdjustScrollbars()
// current client window // current client window
int noPagePositions = (int) ( (h/(double)m_yScrollPixelsPerLine) + 0.5 ); int noPagePositions = (int) ( (h/(double)m_yScrollPixelsPerLine) + 0.5 );
if (noPagePositions < 1) noPagePositions = 1; if (noPagePositions < 1) noPagePositions = 1;
if ( noPagePositions > m_yScrollLines )
noPagePositions = m_yScrollLines;
// Correct position if greater than extent of canvas minus // Correct position if greater than extent of canvas minus
// the visible portion of it or if below zero // 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) ) if ( !wxControlBase::Create(parent, id, pos, size, style, validator, name) )
return FALSE; return FALSE;
m_renderer = wxTheme::Get()->GetRenderer();
m_handler = CreateInputHandler(); m_handler = CreateInputHandler();
SetBackgroundColour(parent->GetBackgroundColour()); SetBackgroundColour(parent->GetBackgroundColour());
@@ -193,13 +192,4 @@ bool wxControl::PerformAction(const wxControlAction& action,
return FALSE; return FALSE;
} }
// ----------------------------------------------------------------------------
// border
// ----------------------------------------------------------------------------
wxBorder wxControl::GetDefaultBorder() const
{
return AcceptsFocus() ? wxBORDER_SUNKEN : wxBORDER_NONE;
}
#endif // wxUSE_CONTROLS #endif // wxUSE_CONTROLS

View File

@@ -62,6 +62,7 @@ void wxListBox::Init()
// will be calculated later when needed // will be calculated later when needed
m_lineHeight = 0; m_lineHeight = 0;
m_itemsPerPage = 0; m_itemsPerPage = 0;
m_maxWidth = 0;
// no items hence no current item // no items hence no current item
m_current = -1; m_current = -1;
@@ -69,8 +70,12 @@ void wxListBox::Init()
// no need to update anything initially // no need to update anything initially
m_updateCount = 0; 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, bool wxListBox::Create(wxWindow *parent,
@@ -83,6 +88,11 @@ bool wxListBox::Create(wxWindow *parent,
const wxValidator& validator, const wxValidator& validator,
const wxString &name) 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) ) if ( !wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name) )
return FALSE; return FALSE;
@@ -113,7 +123,20 @@ int wxListBox::DoAppend(const wxString& item)
size_t index = m_strings.Add(item); size_t index = m_strings.Add(item);
m_clientData.Insert(NULL, index); 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); RefreshItem(m_strings.GetCount() - 1);
@@ -133,7 +156,14 @@ void wxListBox::DoInsertItems(const wxArrayString& items, int pos)
m_clientData.Insert(NULL, pos + n); 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); RefreshItems(pos, count);
} }
@@ -143,6 +173,9 @@ void wxListBox::DoSetItems(const wxArrayString& items, void **clientData)
DoClear(); DoClear();
size_t count = items.GetCount(); size_t count = items.GetCount();
if ( !count )
return;
m_strings.Alloc(count); m_strings.Alloc(count);
m_clientData.Alloc(count); m_clientData.Alloc(count);
for ( size_t n = 0; n < count; n++ ) 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_clientData.Insert(clientData ? clientData[n] : NULL, index);
} }
m_updateScrollbar = TRUE; m_updateScrollbarY = TRUE;
RefreshAll(); 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 // removing strings
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -180,7 +248,7 @@ void wxListBox::Clear()
{ {
DoClear(); DoClear();
m_updateScrollbar = TRUE; m_updateScrollbarY = TRUE;
RefreshAll(); RefreshAll();
} }
@@ -198,7 +266,7 @@ void wxListBox::Delete(int n)
m_clientData.RemoveAt(n); m_clientData.RemoveAt(n);
m_updateScrollbar = TRUE; m_updateScrollbarY = TRUE;
RefreshItems(n, GetCount() - n); RefreshItems(n, GetCount() - n);
} }
@@ -337,8 +405,8 @@ void wxListBox::RefreshItem(int n)
// add this item to the others which we have to refresh // add this item to the others which we have to refresh
if ( m_updateFrom < n ) if ( m_updateFrom < n )
{ {
if ( m_updateCount < n - m_updateFrom ) if ( m_updateCount < n - m_updateFrom + 1 )
m_updateFrom = n - m_updateFrom; m_updateCount = n - m_updateFrom + 1;
} }
else // n <= m_updateFrom else // n <= m_updateFrom
{ {
@@ -355,20 +423,51 @@ void wxListBox::RefreshAll()
void wxListBox::OnIdle(wxIdleEvent& event) void wxListBox::OnIdle(wxIdleEvent& event)
{ {
if ( m_updateScrollbar ) if ( m_updateScrollbarY || m_updateScrollbarX )
{ {
// is our height enough to show all items? wxSize size = GetClientSize();
wxCoord lineHeight = GetLineHeight();
bool showScrollbar = GetCount()*lineHeight > GetClientSize().y;
if ( showScrollbar != m_showScrollbar )
{
// TODO: support for horz scrollbar
SetScrollbars(0, lineHeight, 0, GetCount());
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 ) if ( m_currentChanged )
@@ -390,14 +489,13 @@ void wxListBox::OnIdle(wxIdleEvent& event)
} }
else else
{ {
wxRect rect; wxRect rect = GetClientRect();
rect.x = 0; rect.y += m_updateFrom*GetLineHeight();
rect.y = m_updateFrom*GetLineHeight();
rect.width = 32767; // larger than our size
rect.height = m_updateCount*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)"), 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()); rect.GetTop(), rect.GetBottom());
Refresh(TRUE, &rect); Refresh(TRUE, &rect);
@@ -411,10 +509,16 @@ void wxListBox::OnIdle(wxIdleEvent& event)
// drawing // drawing
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
wxBorder wxListBox::GetDefaultBorder() const
{
return wxBORDER_SUNKEN;
}
void wxListBox::DoDraw(wxControlRenderer *renderer) void wxListBox::DoDraw(wxControlRenderer *renderer)
{ {
#if 0
// draw the border first // draw the border first
if ( m_showScrollbar ) if ( m_showScrollbarY )
{ {
// we need to draw a border around the client area // we need to draw a border around the client area
renderer->GetRect().width -= GetScrollbar(wxVERTICAL)->GetSize().x; renderer->GetRect().width -= GetScrollbar(wxVERTICAL)->GetSize().x;
@@ -422,21 +526,25 @@ void wxListBox::DoDraw(wxControlRenderer *renderer)
// the base class version does it for us // the base class version does it for us
wxControl::DoDraw(renderer); wxControl::DoDraw(renderer);
#endif
// adjust the DC to account for scrolling // adjust the DC to account for scrolling
wxDC& dc = renderer->GetDC(); wxDC& dc = renderer->GetDC();
PrepareDC(dc); PrepareDC(dc);
// get the items which must be redrawn // get the items which must be redrawn
#if 0 #if 1
int y;
GetViewStart(NULL, &y);
wxCoord lineHeight = GetLineHeight(); wxCoord lineHeight = GetLineHeight();
wxRegion rgnUpdate = GetUpdateRegion(); wxRegion rgnUpdate = GetUpdateRegion();
rgnUpdate.Intersect(GetClientRect());
//dc.SetClippingRegion(rgnUpdate); //dc.SetClippingRegion(rgnUpdate);
wxRect rectUpdate = rgnUpdate.GetBox(); 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(); itemMax = m_strings.GetCount();
if ( itemFirst >= itemMax ) if ( itemFirst >= itemMax )
@@ -499,6 +607,25 @@ wxCoord wxListBox::GetLineHeight() const
return m_lineHeight; 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) void wxListBox::OnSize(wxSizeEvent& event)
{ {
// recalculate the number of items per page // recalculate the number of items per page
@@ -509,7 +636,7 @@ void wxListBox::OnSize(wxSizeEvent& event)
void wxListBox::DoSetFirstItem(int n) void wxListBox::DoSetFirstItem(int n)
{ {
wxFAIL_MSG( _T("TODO") ); SetCurrentItem(n);
} }
wxSize wxListBox::DoGetBestClientSize() const wxSize wxListBox::DoGetBestClientSize() const
@@ -582,7 +709,7 @@ void wxListBox::SetCurrentItem(int n)
if ( n != m_current ) if ( n != m_current )
{ {
if ( m_current != -1 ) if ( m_current != -1 )
RefreshItem(n); RefreshItem(m_current);
m_current = n; m_current = n;
@@ -605,7 +732,7 @@ void wxListBox::SetCurrentItem(int n)
void wxListBox::EnsureVisible() void wxListBox::EnsureVisible()
{ {
if ( !m_showScrollbar ) if ( !m_showScrollbarY )
{ {
// nothing to do - everything is shown anyhow // nothing to do - everything is shown anyhow
return; return;
@@ -720,6 +847,7 @@ wxStdListboxInputHandler::wxStdListboxInputHandler(wxInputHandler *handler)
: wxStdInputHandler(handler) : wxStdInputHandler(handler)
{ {
m_winCapture = NULL; m_winCapture = NULL;
m_btnCapture = 0;
} }
int wxStdListboxInputHandler::HitTest(const wxListBox *lbox, int wxStdListboxInputHandler::HitTest(const wxListBox *lbox,
@@ -736,8 +864,8 @@ bool wxStdListboxInputHandler::HandleKey(wxControl *control,
const wxKeyEvent& event, const wxKeyEvent& event,
bool pressed) bool pressed)
{ {
// we're only interested in the key presses // we're only interested in the (normal) key presses
if ( pressed ) if ( pressed && !event.AltDown() )
{ {
wxControlAction action; wxControlAction action;
switch ( event.GetKeyCode() ) 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, // mouse events: for both of them clicking the item selects or toggles it,
// but multiple selection listboxes are different: the item is focused // but multiple selection listboxes are different: the item is focused
// when clicked and only toggled when the button is released // when clicked and only toggled when the button is released
if ( ((control->GetWindowStyle() & wxLB_MULTIPLE) && event.ButtonUp()) if ( (m_btnCapture &&
|| event.ButtonDown() || event.LeftDClick() ) (control->GetWindowStyle() & wxLB_MULTIPLE) &&
event.ButtonUp(m_btnCapture))
|| event.ButtonDown()
|| event.LeftDClick() )
{ {
wxListBox *lbox = wxStaticCast(control, wxListBox); wxListBox *lbox = wxStaticCast(control, wxListBox);
int item = HitTest(lbox, event); int item = HitTest(lbox, event);
if ( item != -1 ) if ( item != -1 )
{ {
wxControlAction action; wxControlAction action;
if ( event.ButtonUp() ) if ( m_btnCapture && event.ButtonUp(m_btnCapture) )
{
if ( m_winCapture )
{ {
m_winCapture->ReleaseMouse(); m_winCapture->ReleaseMouse();
m_winCapture = NULL; 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; action = wxACTION_LISTBOX_TOGGLE;
} }
@@ -797,8 +939,11 @@ bool wxStdListboxInputHandler::HandleMouse(wxControl *control,
// capture the mouse to track the selected item // capture the mouse to track the selected item
m_winCapture = lbox; m_winCapture = lbox;
m_winCapture->CaptureMouse(); m_winCapture->CaptureMouse();
m_btnCapture = event.LeftDown()
action = wxACTION_LISTBOX_SETFOCUS; ? 1
: event.RightDown()
? 3
: 2;
} }
else else
{ {
@@ -809,13 +954,19 @@ bool wxStdListboxInputHandler::HandleMouse(wxControl *control,
{ {
action = wxACTION_LISTBOX_SELECT; action = wxACTION_LISTBOX_SELECT;
} }
// in any case, clicking an item makes it the current one
lbox->PerformAction(wxACTION_LISTBOX_SETFOCUS, item);
} }
else // event.LeftDClick() else // event.LeftDClick()
{ {
action = wxACTION_LISTBOX_ACTIVATE; action = wxACTION_LISTBOX_ACTIVATE;
} }
if ( !!action )
{
lbox->PerformAction(action, item); lbox->PerformAction(action, item);
}
return TRUE; return TRUE;
} }

View File

@@ -325,14 +325,6 @@ void wxControlRenderer::DrawBorder()
// draw outline // draw outline
m_renderer->DrawBorder(m_dc, m_window->GetBorder(), m_renderer->DrawBorder(m_dc, m_window->GetBorder(),
m_rect, flags, &m_rect); 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, void wxControlRenderer::DrawLabel(const wxBitmap& bitmap,
@@ -397,14 +389,21 @@ void wxControlRenderer::DrawBitmap(const wxBitmap& bitmap)
} }
void wxControlRenderer::DrawBackgroundBitmap() void wxControlRenderer::DrawBackgroundBitmap()
{
if ( m_window->GetBackgroundBitmap().Ok() )
{ {
// get the bitmap and the flags // get the bitmap and the flags
int alignment; int alignment;
wxStretch stretch; wxStretch stretch;
wxBitmap bmp = m_window->GetBackgroundBitmap(&alignment, &stretch); wxBitmap bmp = m_window->GetBackgroundBitmap(&alignment, &stretch);
DrawBitmap(bmp, m_rect, 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, void wxControlRenderer::DrawBitmap(const wxBitmap& bitmap,
const wxRect& rect, const wxRect& rect,
@@ -549,7 +548,7 @@ void wxControlRenderer::DrawScrollbar(const wxScrollBar *scrollbar,
// and the thumb // and the thumb
wxScrollBar::Element elem = wxScrollBar::Element_Thumb; wxScrollBar::Element elem = wxScrollBar::Element_Thumb;
wxRect rectThumb = m_renderer->GetScrollbarRect(scrollbar, elem); 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)"), wxLogTrace(_T("scroll"), _T("drawing thumb at (%d, %d)-(%d, %d)"),
rectThumb.GetLeft(), rectThumb.GetLeft(),
@@ -580,13 +579,31 @@ void wxControlRenderer::DrawItems(const wxListBox *lbox,
{ {
// prepare for the drawing: calc the initial position // prepare for the drawing: calc the initial position
wxCoord lineHeight = lbox->GetLineHeight(); wxCoord lineHeight = lbox->GetLineHeight();
int lines, pixelsPerLine;
lbox->GetViewStart(NULL, &lines); // note that SetClippingRegion() needs the physical (unscrolled)
lbox->GetScrollPixelsPerUnit(NULL, &pixelsPerLine); // coordinates while we use the logical (scrolled) ones for the drawing
wxRect rect = m_rect; // itself
rect.y += itemFirst*lineHeight - lines*pixelsPerLine; 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; 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 // 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 // make sure that we never set wxCONTROL_FOCUSED flag if it doesn't
int itemCurrent = wxTheApp->IsActive() ? lbox->GetCurrentItem() : -1; int itemCurrent = wxTheApp->IsActive() ? lbox->GetCurrentItem() : -1;

View File

@@ -54,12 +54,19 @@ public:
const wxControlAction& action, const wxControlAction& action,
wxScrollBar *control); wxScrollBar *control);
void StartAutoScroll();
virtual void Notify(); virtual void Notify();
protected:
void DoNotify();
private: private:
wxStdScrollBarInputHandler *m_handler; wxStdScrollBarInputHandler *m_handler;
wxControlAction m_action; wxControlAction m_action;
wxScrollBar *m_control; wxScrollBar *m_control;
bool m_skipNext;
}; };
// ============================================================================ // ============================================================================
@@ -101,9 +108,8 @@ bool wxScrollBar::Create(wxWindow *parent,
const wxValidator& validator, const wxValidator& validator,
const wxString &name) const wxString &name)
{ {
// the scrollbars always have the standard border so far // the scrollbars never have the border
style &= ~wxBORDER_MASK; style &= ~wxBORDER_MASK;
style |= wxBORDER_SUNKEN;
if ( !wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name) ) if ( !wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name) )
return FALSE; return FALSE;
@@ -221,9 +227,14 @@ void wxScrollBar::OnIdle(wxIdleEvent& event)
{ {
// we try to avoid redrawing the entire shaft (which might // we try to avoid redrawing the entire shaft (which might
// be quite long) if possible by only redrawing the area // be quite long) if possible by only redrawing the area
// between the old and current positions of the thumb // wich really changed
if ( m_thumbPosOld != -1 ) 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 = wxRect rectOld =
GetRenderer()->GetScrollbarRect(this, GetRenderer()->GetScrollbarRect(this,
(Element)n, (Element)n,
@@ -233,15 +244,21 @@ void wxScrollBar::OnIdle(wxIdleEvent& event)
if ( n == Element_Bar_1 ) if ( n == Element_Bar_1 )
rect.SetTop(rectOld.GetBottom()); rect.SetTop(rectOld.GetBottom());
else else
rect.SetBottom(rect.GetTop()); rect.SetBottom(rectOld.GetBottom());
} }
else // horizontal else // horizontal
{ {
if ( n == Element_Bar_1 ) if ( n == Element_Bar_1 )
rect.SetLeft(rectOld.GetRight()); rect.SetLeft(rectOld.GetRight());
else 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); 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) 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; 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, bool wxScrollBar::PerformAction(const wxControlAction& action,
long numArg, long numArg,
const wxString& strArg) const wxString& strArg)
@@ -389,11 +420,40 @@ wxScrollBarTimer::wxScrollBarTimer(wxStdScrollBarInputHandler *handler,
m_handler = handler; m_handler = handler;
m_action = action; m_action = action;
m_control = control; 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() 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 // start dragging
if ( hasAction ) if ( hasAction )
{ {
m_timerScroll = new wxScrollBarTimer(this, // this slightly unreadable code is necessary because
action, // m_timerScroll is of class wxTimer, not wxScrollBarTimer
scrollbar); wxScrollBarTimer *timerScroll =
// start scrolling immediately new wxScrollBarTimer(this, action, scrollbar);
m_timerScroll->Notify(); m_timerScroll = timerScroll;
timerScroll->StartAutoScroll();
// and continue it later
m_timerScroll->Start(50); // FIXME hardcoded delay
} }
//else: no (immediate) action //else: no (immediate) action

View File

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

View File

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

View File

@@ -73,7 +73,31 @@ void wxWindow::Init()
m_isCurrent = FALSE; 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 // the event handler executed when the window background must be painted
void wxWindow::OnErase(wxEraseEvent& event) void wxWindow::OnErase(wxEraseEvent& event)
{ {
wxControlRenderer renderer(this, *event.GetDC(), wxControlRenderer renderer(this, *event.GetDC(), m_renderer);
wxTheme::Get()->GetRenderer());
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 wxRect rectCorner;
event.Skip(); 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); wxPaintDC dc(this);
wxControlRenderer renderer(this, dc, m_renderer); wxControlRenderer renderer(this, dc, m_renderer);
// do draw the control! // first, draw the border
DoDrawBorder(&renderer);
// and then draw the control
DoDraw(&renderer); DoDraw(&renderer);
} }
} }
bool wxWindow::DoDrawBackground(wxControlRenderer *renderer) bool wxWindow::DoDrawBackground(wxControlRenderer *renderer)
{ {
if ( !m_bitmapBg.Ok() )
return FALSE;
renderer->DrawBackgroundBitmap(); renderer->DrawBackgroundBitmap();
return TRUE; return TRUE;
} }
void wxWindow::DoDraw(wxControlRenderer *renderer) void wxWindow::DoDrawBorder(wxControlRenderer *renderer)
{ {
renderer->DrawBorder(); renderer->DrawBorder();
} }
void wxWindow::DoDraw(wxControlRenderer *renderer)
{
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// state flags // state flags
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -251,15 +288,39 @@ void wxWindow::DoSetClientSize(int width, int height)
wxWindowNative::DoSetClientSize(width, 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 void wxWindow::DoGetClientSize(int *width, int *height) const
{ {
wxWindowNative::DoGetClientSize(width, height); wxWindowNative::DoGetClientSize(width, height);
if ( width && m_scrollbarVert ) wxRect rectBorder;
if ( m_renderer )
rectBorder = m_renderer->GetBorderDimensions(GetBorder());
if ( width )
{
if ( m_scrollbarVert )
*width -= m_scrollbarVert->GetSize().x; *width -= m_scrollbarVert->GetSize().x;
if ( height && m_scrollbarHorz ) *width -= rectBorder.x + rectBorder.width;
}
if ( height )
{
if ( m_scrollbarHorz )
*height -= m_scrollbarHorz->GetSize().y; *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() void wxWindow::PositionScrollbars()
{ {
wxCoord x, y; wxRect rectClient = GetClientRect();
DoGetSize(&x, &y);
int width = m_scrollbarVert ? m_scrollbarVert->GetSize().x : 0; int width = m_scrollbarVert ? m_scrollbarVert->GetSize().x : 0;
int height = m_scrollbarHorz ? m_scrollbarHorz->GetSize().y : 0; int height = m_scrollbarHorz ? m_scrollbarHorz->GetSize().y : 0;
if ( m_scrollbarVert ) 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 ) 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, void wxWindow::SetScrollbar(int orient,
int pos, int pos,
int thumb, int pageSize,
int range, int range,
bool refresh) bool refresh)
{ {
@@ -305,12 +376,23 @@ void wxWindow::SetScrollbar(int orient,
PositionScrollbars(); 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 else // no range means no scrollbar
{ {
if ( scrollbar ) if ( scrollbar )
{
if ( GetWindowStyle() & wxALWAYS_SHOW_SB )
{
scrollbar->Disable();
}
else
{ {
delete scrollbar; delete scrollbar;
@@ -321,6 +403,7 @@ void wxWindow::SetScrollbar(int orient,
} }
} }
} }
}
void wxWindow::SetScrollPos(int orient, int pos, bool refresh) void wxWindow::SetScrollPos(int orient, int pos, bool refresh)
{ {
@@ -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"), wxLogTrace(_T("scroll"), _T("window is %dx%d, scroll by %d, %d"),
sizeTotal.x, sizeTotal.y, dx, dy); sizeTotal.x, sizeTotal.y, dx, dy);
wxPoint ptSource, ptDest; wxPoint ptSource, ptDest, ptOrigin;
ptSource =
ptDest =
ptOrigin = GetClientAreaOrigin();
wxSize size; wxSize size;
size.x = sizeTotal.x - abs(dx); size.x = sizeTotal.x - abs(dx);
size.y = sizeTotal.y - abs(dy); size.y = sizeTotal.y - abs(dy);
@@ -386,27 +472,23 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
if ( dx < 0 ) if ( dx < 0 )
{ {
// scroll to the right, move to the left // scroll to the right, move to the left
ptSource.x = -dx; ptSource.x -= dx;
ptDest.x = 0;
} }
else else
{ {
// scroll to the left, move to the right // scroll to the left, move to the right
ptSource.x = 0; ptDest.x += dx;
ptDest.x = dx;
} }
if ( dy < 0 ) if ( dy < 0 )
{ {
// scroll down, move up // scroll down, move up
ptSource.y = -dy; ptSource.y -= dy;
ptDest.y = 0;
} }
else else
{ {
// scroll up, move down // scroll up, move down
ptSource.y = 0; ptDest.y += dy;
ptDest.y = dy;
} }
// do move // do move
@@ -429,23 +511,23 @@ void wxWindow::ScrollWindow(int dx, int dy, const wxRect *rect)
// it bad? // it bad?
wxRect rect; wxRect rect;
rect.x = ptOrigin.x;
rect.y = ptOrigin.y;
if ( dx ) if ( dx )
{ {
if ( dx < 0 ) if ( dx < 0 )
{ {
// refresh the area along the right border // refresh the area along the right border
rect.x = size.x; rect.x += size.x;
rect.width = -dx; rect.width = -dx;
} }
else else
{ {
// refresh the area along the left border // refresh the area along the left border
rect.x = 0;
rect.width = dx; rect.width = dx;
} }
rect.y = 0;
rect.height = sizeTotal.y; rect.height = sizeTotal.y;
wxLogTrace(_T("scroll"), _T("refreshing (%d, %d)-(%d, %d)"), 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 ) if ( dy < 0 )
{ {
// refresh the area along the bottom border // refresh the area along the bottom border
rect.y = size.y; rect.y += size.y;
rect.height = -dy; rect.height = -dy;
} }
else else
{ {
// refresh the area along the top border // refresh the area along the top border
rect.y = 0;
rect.height = dy; rect.height = dy;
} }
rect.x = 0;
rect.width = sizeTotal.x; rect.width = sizeTotal.x;
wxLogTrace(_T("scroll"), _T("refreshing (%d, %d)-(%d, %d)"), wxLogTrace(_T("scroll"), _T("refreshing (%d, %d)-(%d, %d)"),