1. big wxScrollBar optimization: Refresh() doesn't refresh them any more

2. many fixes to refresh scrollbars when needed (as this is not done all
   the time now)
3. wxStdButtonInputHandler bug with uninit m_hasMouse fixing bug with
   moving mouse with pressed left button into button
4. wxRadioBox::SetSelection() and wxRadioButton::SetValue() clear the
   values of the other buttons in the same radio group
5. wxTextCtrl::RefreshPixelRange() calculates the end of line correctly
6. tons of wxListBox fixes
7. removed confusing "Create" button from the lbox sample, listbox is now
   recreated on the fly


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/wxUNIVERSAL@8615 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2000-10-23 01:45:21 +00:00
parent 1f720ce54b
commit d131b63b6d
16 changed files with 243 additions and 128 deletions

View File

@@ -114,6 +114,9 @@ protected:
// send command event notifying about the checkbox state change // send command event notifying about the checkbox state change
virtual void SendEvent(); virtual void SendEvent();
// called when the checkbox becomes checked - radio button hook
virtual void OnCheck();
// get the state corresponding to the flags (combination of wxCONTROL_XXX) // get the state corresponding to the flags (combination of wxCONTROL_XXX)
wxCheckBox::State GetState(int flags) const; wxCheckBox::State GetState(int flags) const;

View File

@@ -112,9 +112,6 @@ public:
// override some more base class methods // override some more base class methods
virtual bool SetFont(const wxFont& font); virtual bool SetFont(const wxFont& font);
virtual void Refresh( bool eraseBackground = TRUE,
const wxRect *rect = (const wxRect *) NULL );
// the wxUniversal-specific methods // the wxUniversal-specific methods
// -------------------------------- // --------------------------------

View File

@@ -66,8 +66,12 @@ protected:
// another radiobutton // another radiobutton
void ClearValue(); void ClearValue();
// called when the radio button becomes checked: we clear all the buttons
// in the same group with us here
virtual void OnCheck();
// send event about radio button selection // send event about radio button selection
void SendEvent(); virtual void SendEvent();
private: private:
DECLARE_DYNAMIC_CLASS(wxRadioButton) DECLARE_DYNAMIC_CLASS(wxRadioButton)

View File

@@ -256,6 +256,9 @@ protected:
// get the extent (width) of the text // get the extent (width) of the text
wxCoord GetTextWidth(const wxString& text) const; wxCoord GetTextWidth(const wxString& text) const;
// get the logical text width (accounting for scrolling)
wxCoord GetTotalWidth() const;
// refresh the text in the given (in logical coords) rect // refresh the text in the given (in logical coords) rect
void RefreshTextRect(wxRect& rect); void RefreshTextRect(wxRect& rect);

View File

@@ -155,6 +155,10 @@ public:
// this with both dx and dy non zero) // this with both dx and dy non zero)
wxRect ScrollNoRefresh(int dx, int dy, const wxRect *rect = NULL); wxRect ScrollNoRefresh(int dx, int dy, const wxRect *rect = NULL);
// after scrollbars are added or removed they must be refreshed by calling
// this function
void RefreshScrollbars();
// overridden base class methods // overridden base class methods
// ----------------------------- // -----------------------------

View File

@@ -67,7 +67,6 @@
enum enum
{ {
LboxTest_Reset = 100, LboxTest_Reset = 100,
LboxTest_Create,
LboxTest_Add, LboxTest_Add,
LboxTest_AddText, LboxTest_AddText,
LboxTest_AddSeveral, LboxTest_AddSeveral,
@@ -111,7 +110,6 @@ public:
protected: protected:
// event handlers // event handlers
void OnButtonReset(wxCommandEvent& event); void OnButtonReset(wxCommandEvent& event);
void OnButtonCreate(wxCommandEvent& event);
void OnButtonChange(wxCommandEvent& event); void OnButtonChange(wxCommandEvent& event);
void OnButtonDelete(wxCommandEvent& event); void OnButtonDelete(wxCommandEvent& event);
void OnButtonDeleteSel(wxCommandEvent& event); void OnButtonDeleteSel(wxCommandEvent& event);
@@ -128,10 +126,10 @@ protected:
void OnCheckOrRadioBox(wxCommandEvent& event); void OnCheckOrRadioBox(wxCommandEvent& event);
void OnUpdateUIAddSeveral(wxUpdateUIEvent& event); void OnUpdateUIAddSeveral(wxUpdateUIEvent& event);
void OnUpdateUICreateButton(wxUpdateUIEvent& event);
void OnUpdateUIClearButton(wxUpdateUIEvent& event); void OnUpdateUIClearButton(wxUpdateUIEvent& event);
void OnUpdateUIDeleteButton(wxUpdateUIEvent& event); void OnUpdateUIDeleteButton(wxUpdateUIEvent& event);
void OnUpdateUIDeleteSelButton(wxUpdateUIEvent& event); void OnUpdateUIDeleteSelButton(wxUpdateUIEvent& event);
void OnUpdateUIResetButton(wxUpdateUIEvent& event);
// reset the listbox parameters // reset the listbox parameters
void Reset(); void Reset();
@@ -157,9 +155,6 @@ protected:
bool m_horzScroll, bool m_horzScroll,
m_vertScrollAlways; m_vertScrollAlways;
// should the recreate button be enabled?
bool m_dirty;
// the controls // the controls
// ------------ // ------------
@@ -267,7 +262,6 @@ IMPLEMENT_APP(LboxTestApp)
BEGIN_EVENT_TABLE(LboxTestFrame, wxFrame) BEGIN_EVENT_TABLE(LboxTestFrame, wxFrame)
EVT_BUTTON(LboxTest_Reset, LboxTestFrame::OnButtonReset) EVT_BUTTON(LboxTest_Reset, LboxTestFrame::OnButtonReset)
EVT_BUTTON(LboxTest_Create, LboxTestFrame::OnButtonCreate)
EVT_BUTTON(LboxTest_Change, LboxTestFrame::OnButtonChange) EVT_BUTTON(LboxTest_Change, LboxTestFrame::OnButtonChange)
EVT_BUTTON(LboxTest_Delete, LboxTestFrame::OnButtonDelete) EVT_BUTTON(LboxTest_Delete, LboxTestFrame::OnButtonDelete)
EVT_BUTTON(LboxTest_DeleteSel, LboxTestFrame::OnButtonDeleteSel) EVT_BUTTON(LboxTest_DeleteSel, LboxTestFrame::OnButtonDeleteSel)
@@ -281,9 +275,7 @@ BEGIN_EVENT_TABLE(LboxTestFrame, wxFrame)
EVT_TEXT_ENTER(LboxTest_AddText, LboxTestFrame::OnButtonAdd) EVT_TEXT_ENTER(LboxTest_AddText, LboxTestFrame::OnButtonAdd)
EVT_TEXT_ENTER(LboxTest_DeleteText, LboxTestFrame::OnButtonDelete) EVT_TEXT_ENTER(LboxTest_DeleteText, LboxTestFrame::OnButtonDelete)
EVT_UPDATE_UI_RANGE(LboxTest_Reset, LboxTest_Create, EVT_UPDATE_UI(LboxTest_Reset, LboxTestFrame::OnUpdateUIResetButton)
LboxTestFrame::OnUpdateUICreateButton)
EVT_UPDATE_UI(LboxTest_AddSeveral, LboxTestFrame::OnUpdateUIAddSeveral) EVT_UPDATE_UI(LboxTest_AddSeveral, LboxTestFrame::OnUpdateUIAddSeveral)
EVT_UPDATE_UI(LboxTest_Clear, LboxTestFrame::OnUpdateUIClearButton) EVT_UPDATE_UI(LboxTest_Clear, LboxTestFrame::OnUpdateUIClearButton)
EVT_UPDATE_UI(LboxTest_DeleteText, LboxTestFrame::OnUpdateUIClearButton) EVT_UPDATE_UI(LboxTest_DeleteText, LboxTestFrame::OnUpdateUIClearButton)
@@ -325,7 +317,6 @@ LboxTestFrame::LboxTestFrame(const wxString& title)
: wxFrame(NULL, -1, title, wxPoint(100, 100)) : wxFrame(NULL, -1, title, wxPoint(100, 100))
{ {
// init everything // init everything
m_dirty = FALSE;
m_radioSelMode = (wxRadioBox *)NULL; m_radioSelMode = (wxRadioBox *)NULL;
m_chkVScroll = m_chkVScroll =
@@ -377,12 +368,8 @@ LboxTestFrame::LboxTestFrame(const wxString& title)
sizerLeft->Add(5, 5, 0, wxGROW | wxALL, 5); // spacer sizerLeft->Add(5, 5, 0, wxGROW | wxALL, 5); // spacer
sizerLeft->Add(m_radioSelMode, 0, wxGROW | wxALL, 5); sizerLeft->Add(m_radioSelMode, 0, wxGROW | wxALL, 5);
wxSizer *sizerBtn = new wxBoxSizer(wxHORIZONTAL);
wxButton *btn = new wxButton(m_panel, LboxTest_Reset, _T("&Reset")); wxButton *btn = new wxButton(m_panel, LboxTest_Reset, _T("&Reset"));
sizerBtn->Add(btn, 0, wxLEFT | wxRIGHT, 5); sizerLeft->Add(btn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 15);
btn = new wxButton(m_panel, LboxTest_Create, _T("&Create"));
sizerBtn->Add(btn, 0, wxLEFT | wxRIGHT, 5);
sizerLeft->Add(sizerBtn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 15);
// middle pane // middle pane
wxStaticBox *box2 = new wxStaticBox(m_panel, -1, _T("&Change listbox contents")); wxStaticBox *box2 = new wxStaticBox(m_panel, -1, _T("&Change listbox contents"));
@@ -452,13 +439,12 @@ LboxTestFrame::LboxTestFrame(const wxString& title)
sizerDown->Add(sizerBtns, 0, wxALL | wxALIGN_RIGHT, 5); sizerDown->Add(sizerBtns, 0, wxALL | wxALIGN_RIGHT, 5);
// put everything together // put everything together
sizerTop->Add(sizerUp, 1, wxGROW | (wxALL & ~wxBOTTOM), 10); sizerTop->Add(sizerUp, 1, wxGROW | (wxALL & ~(wxTOP | wxBOTTOM)), 10);
sizerTop->Add(0, 5, 0, wxGROW); // spacer in between sizerTop->Add(0, 5, 0, wxGROW); // spacer in between
sizerTop->Add(sizerDown, 0, wxGROW | (wxALL & ~wxTOP), 10); sizerTop->Add(sizerDown, 0, wxGROW | (wxALL & ~wxTOP), 10);
// final initialization // final initialization
Reset(); Reset();
m_dirty = FALSE;
m_panel->SetAutoLayout(TRUE); m_panel->SetAutoLayout(TRUE);
m_panel->SetSizer(sizerTop); m_panel->SetSizer(sizerTop);
@@ -483,21 +469,10 @@ LboxTestFrame::~LboxTestFrame()
void LboxTestFrame::Reset() void LboxTestFrame::Reset()
{ {
if ( m_radioSelMode->GetSelection() == LboxSel_Single &&
!m_chkSort->GetValue() &&
m_chkHScroll->GetValue() &&
!m_chkVScroll->GetValue() )
{
// nothing to do
return;
}
m_radioSelMode->SetSelection(LboxSel_Single); m_radioSelMode->SetSelection(LboxSel_Single);
m_chkSort->SetValue(FALSE); m_chkSort->SetValue(FALSE);
m_chkHScroll->SetValue(TRUE); m_chkHScroll->SetValue(TRUE);
m_chkVScroll->SetValue(FALSE); m_chkVScroll->SetValue(FALSE);
m_dirty = TRUE;
} }
void LboxTestFrame::CreateLbox() void LboxTestFrame::CreateLbox()
@@ -540,8 +515,6 @@ void LboxTestFrame::CreateLbox()
m_lbox->Set(items); m_lbox->Set(items);
m_sizerLbox->Add(m_lbox, 1, wxGROW | wxALL, 5); m_sizerLbox->Add(m_lbox, 1, wxGROW | wxALL, 5);
m_sizerLbox->Layout(); m_sizerLbox->Layout();
m_dirty = FALSE;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -556,10 +529,7 @@ void LboxTestFrame::OnButtonQuit(wxCommandEvent& WXUNUSED(event))
void LboxTestFrame::OnButtonReset(wxCommandEvent& WXUNUSED(event)) void LboxTestFrame::OnButtonReset(wxCommandEvent& WXUNUSED(event))
{ {
Reset(); Reset();
}
void LboxTestFrame::OnButtonCreate(wxCommandEvent& WXUNUSED(event))
{
CreateLbox(); CreateLbox();
} }
@@ -638,9 +608,12 @@ void LboxTestFrame::OnButtonAddSeveral(wxCommandEvent& event)
m_lbox->InsertItems(items, 0); m_lbox->InsertItems(items, 0);
} }
void LboxTestFrame::OnUpdateUICreateButton(wxUpdateUIEvent& event) void LboxTestFrame::OnUpdateUIResetButton(wxUpdateUIEvent& event)
{ {
event.Enable(m_dirty); event.Enable( (m_radioSelMode->GetSelection() != LboxSel_Single) ||
m_chkSort->GetValue() ||
!m_chkHScroll->GetValue() ||
m_chkVScroll->GetValue() );
} }
void LboxTestFrame::OnUpdateUIDeleteButton(wxUpdateUIEvent& event) void LboxTestFrame::OnUpdateUIDeleteButton(wxUpdateUIEvent& event)
@@ -681,6 +654,6 @@ void LboxTestFrame::OnListboxDClick(wxCommandEvent& event)
void LboxTestFrame::OnCheckOrRadioBox(wxCommandEvent& event) void LboxTestFrame::OnCheckOrRadioBox(wxCommandEvent& event)
{ {
m_dirty = TRUE; CreateLbox();
} }

View File

@@ -384,7 +384,7 @@ MyUnivFrame::MyUnivFrame(const wxString& title)
new wxTextCtrl(this, -1, _T("Hello, Universe!"), new wxTextCtrl(this, -1, _T("Hello, Universe!"),
wxPoint(550, 150), wxDefaultSize); wxPoint(550, 150), wxDefaultSize);
#else // TEST_TEXT_ONLY #else // TEST_TEXT_ONLY
#if 0 #if 1
wxTextCtrl *text = new wxTextCtrl(this, -1, _T("Hello, Universe!"), wxTextCtrl *text = new wxTextCtrl(this, -1, _T("Hello, Universe!"),
wxPoint(10, 40)); wxPoint(10, 40));
text->SetFont(wxFont(24, wxFONTFAMILY_DEFAULT, text->SetFont(wxFont(24, wxFONTFAMILY_DEFAULT,

View File

@@ -304,7 +304,7 @@ void wxScrollHelper::HandleOnScroll(wxScrollWinEvent& event)
if ( needsRefresh ) if ( needsRefresh )
{ {
m_targetWindow->Refresh(GetRect()); m_targetWindow->Refresh(TRUE, GetRect());
} }
else else
{ {

View File

@@ -242,6 +242,7 @@ wxStdButtonInputHandler::wxStdButtonInputHandler(wxInputHandler *handler)
: wxStdInputHandler(handler) : wxStdInputHandler(handler)
{ {
m_winCapture = NULL; m_winCapture = NULL;
m_winHasMouse = FALSE;
} }
bool wxStdButtonInputHandler::HandleKey(wxControl *control, bool wxStdButtonInputHandler::HandleKey(wxControl *control,

View File

@@ -92,10 +92,21 @@ void wxCheckBox::SetValue(bool value)
{ {
m_status = status; m_status = status;
if ( m_status == Status_Checked )
{
// invoke the hook
OnCheck();
}
Refresh(); Refresh();
} }
} }
void wxCheckBox::OnCheck()
{
// we do nothing here
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// indicator bitmaps // indicator bitmaps
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -245,6 +245,7 @@ void wxListBox::DoClear()
} }
m_itemsClientData.Clear(); m_itemsClientData.Clear();
m_selections.Clear();
} }
void wxListBox::Clear() void wxListBox::Clear()
@@ -371,6 +372,9 @@ void wxListBox::SetSelection(int n, bool select)
} }
//else: not selected //else: not selected
} }
wxASSERT_MSG( HasMultipleSelection() || (m_selections.GetCount() < 2),
_T("multiple selected items in single selection lbox?") );
} }
int wxListBox::GetSelection() const int wxListBox::GetSelection() const
@@ -390,9 +394,15 @@ int wxListBox::GetSelections(wxArrayInt& selections) const
{ {
// always return sorted array to the user // always return sorted array to the user
selections = m_selections; selections = m_selections;
selections.Sort(wxCompareInts); size_t count = m_selections.GetCount();
return m_selections.GetCount(); // don't call sort on an empty array
if ( count )
{
selections.Sort(wxCompareInts);
}
return count;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -401,18 +411,6 @@ int wxListBox::GetSelections(wxArrayInt& selections) const
// added/deleted/changed subsequently // added/deleted/changed subsequently
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void wxListBox::Refresh(bool eraseBackground, const wxRect *rect)
{
if ( rect )
wxLogTrace(_T("listbox"), _T("Refreshing (%d, %d)-(%d, %d)"),
rect->x, rect->y,
rect->x + rect->width, rect->y + rect->height);
else
wxLogTrace(_T("listbox"), _T("Refreshing all"));
wxControl::Refresh(eraseBackground, rect);
}
void wxListBox::RefreshFromItemToEnd(int from) void wxListBox::RefreshFromItemToEnd(int from)
{ {
RefreshItems(from, GetCount() - from); RefreshItems(from, GetCount() - from);
@@ -515,9 +513,12 @@ void wxListBox::UpdateScrollbars()
// what should be the scrollbar range now? // what should be the scrollbar range now?
int scrollRangeX = showScrollbarX int scrollRangeX = showScrollbarX
? (maxWidth + 2*charWidth - 1) / charWidth ? (maxWidth + charWidth - 1) / charWidth + 2 // FIXME
: 0;
int scrollRangeY = showScrollbarY
? nLines +
(size.y % lineHeight + lineHeight - 1) / lineHeight
: 0; : 0;
int scrollRangeY = showScrollbarY ? nLines : 0;
// reset scrollbars if something changed: either the visibility status // reset scrollbars if something changed: either the visibility status
// or the range of a scrollbar which is shown // or the range of a scrollbar which is shown
@@ -558,7 +559,10 @@ void wxListBox::UpdateItems()
rect.height = size.y; rect.height = size.y;
rect.y += m_updateFrom*GetLineHeight(); rect.y += m_updateFrom*GetLineHeight();
rect.height = m_updateCount*GetLineHeight(); rect.height = m_updateCount*GetLineHeight();
CalcScrolledPosition(rect.x, rect.y, &rect.x, &rect.y);
// we don't need to calculate x position as we always refresh the
// entire line(s)
CalcScrolledPosition(0, rect.y, NULL, &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 - 1, m_updateFrom, m_updateFrom + m_updateCount - 1,
@@ -948,8 +952,15 @@ void wxListBox::Activate(int item)
{ {
if ( item != -1 ) if ( item != -1 )
SetCurrentItem(item); SetCurrentItem(item);
else
item = m_current;
if ( m_current != -1 ) if ( !(GetWindowStyle() & wxLB_MULTIPLE) )
{
DeselectAll(item);
}
if ( item != -1 )
{ {
Select(); Select();

View File

@@ -72,6 +72,48 @@ bool wxRadioButton::Create(wxWindow *parent,
// radio button methods // radio button methods
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void wxRadioButton::OnCheck()
{
// clear all others radio buttons in our group: for this we need to
// find the radio button which is the first in the group, i.e. the one
// with wxRB_GROUP style
const wxWindowList& siblings = GetParent()->GetChildren();
wxWindowList::Node *nodeStart = siblings.Find(this);
while ( nodeStart )
{
// stop if we found a radio button with wxRB_GROUP style or it we
// are at the first control
if ( !nodeStart->GetPrevious() ||
(nodeStart->GetData()->GetWindowStyle() & wxRB_GROUP) )
break;
nodeStart = nodeStart->GetPrevious();
}
// now clear all radio buttons from the starting one until the next
// one with wxRB_GROUP style
while ( nodeStart )
{
wxWindow *win = nodeStart->GetData();
if ( win != this )
{
wxRadioButton *btn = wxDynamicCast(win, wxRadioButton);
if ( btn )
{
btn->ClearValue();
}
}
nodeStart = nodeStart->GetNext();
if ( !nodeStart ||
(nodeStart->GetData()->GetWindowStyle() & wxRB_GROUP) )
{
// we reached the next group
break;
}
}
}
void wxRadioButton::ChangeValue(bool value) void wxRadioButton::ChangeValue(bool value)
{ {
if ( value == IsChecked() ) if ( value == IsChecked() )
@@ -79,52 +121,11 @@ void wxRadioButton::ChangeValue(bool value)
if ( !IsChecked() ) if ( !IsChecked() )
{ {
// clear all others radio buttons in our group: for this we need to wxCheckBox::ChangeValue(value);
// find the radio button which is the first in the group, i.e. the one
// with wxRB_GROUP style
const wxWindowList& siblings = GetParent()->GetChildren();
wxWindowList::Node *nodeStart = siblings.Find(this);
while ( nodeStart )
{
// stop if we found a radio button with wxRB_GROUP style or it we
// are at the first control
if ( !nodeStart->GetPrevious() ||
(nodeStart->GetData()->GetWindowStyle() & wxRB_GROUP) )
break;
nodeStart = nodeStart->GetPrevious();
}
// now clear all radio buttons from the starting one until the next
// one with wxRB_GROUP style
while ( nodeStart )
{
wxWindow *win = nodeStart->GetData();
if ( win != this )
{
wxRadioButton *btn = wxDynamicCast(win, wxRadioButton);
if ( btn )
{
btn->ClearValue();
}
}
nodeStart = nodeStart->GetNext();
if ( !nodeStart ||
(nodeStart->GetData()->GetWindowStyle() & wxRB_GROUP) )
{
// we reached the next group
break;
}
}
SetValue(TRUE);
SendEvent();
} }
else // attempt to clear a radio button - this can't be done else // attempt to clear a radio button - this can't be done
{ {
// but still refresh as ou PRESSED flag changed // but still refresh as our PRESSED flag changed
Refresh(); Refresh();
} }
} }

View File

@@ -497,6 +497,23 @@ void wxControlRenderer::DrawScrollbar(const wxScrollBar *scrollbar,
rectUpdate.GetTop(), rectUpdate.GetTop(),
rectUpdate.GetRight(), rectUpdate.GetRight(),
rectUpdate.GetBottom()); rectUpdate.GetBottom());
#if 0 //def WXDEBUG_SCROLLBAR
static bool s_refreshDebug = FALSE;
if ( s_refreshDebug )
{
wxClientDC dc(wxConstCast(scrollbar, wxScrollBar));
dc.SetBrush(*wxRED_BRUSH);
dc.SetPen(*wxTRANSPARENT_PEN);
dc.DrawRectangle(rectUpdate);
// under Unix we use "--sync" X option for this
#ifdef __WXMSW__
::GdiFlush();
::Sleep(200);
#endif // __WXMSW__
}
#endif // WXDEBUG_SCROLLBAR
} }
wxOrientation orient = scrollbar->IsVertical() ? wxVERTICAL wxOrientation orient = scrollbar->IsVertical() ? wxVERTICAL
@@ -620,18 +637,15 @@ void wxControlRenderer::DoDrawItems(const wxListBox *lbox,
// scrollbar for the long strings // scrollbar for the long strings
m_dc.SetClippingRegion(rect.x, rect.y, rect.width + 1, rect.height + 1); 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 // adjust the rect position now
lbox->CalcScrolledPosition(rect.x, rect.y, &rect.x, &rect.y); lbox->CalcScrolledPosition(rect.x, rect.y, &rect.x, &rect.y);
rect.y += itemFirst*lineHeight; rect.y += itemFirst*lineHeight;
rect.height = lineHeight; rect.height = lineHeight;
// the rect should go to the right visible border so adjust the width if x
// is shifted (rightmost point should stay the same)
rect.width -= rect.x;
// we'll keep the text colour unchanged // we'll keep the text colour unchanged
m_dc.SetTextForeground(lbox->GetForegroundColour()); m_dc.SetTextForeground(lbox->GetForegroundColour());

View File

@@ -41,6 +41,12 @@
#include "wx/univ/inphand.h" #include "wx/univ/inphand.h"
#include "wx/univ/theme.h" #include "wx/univ/theme.h"
#define WXDEBUG_SCROLLBAR
#ifndef __WXDEBUG__
#undef WXDEBUG_SCROLLBAR
#endif // !__WXDEBUG__
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxScrollBarTimer: this class is used to repeatedly scroll the scrollbar // wxScrollBarTimer: this class is used to repeatedly scroll the scrollbar
// when the mouse is help pressed on the arrow or on the bar. It generates the // when the mouse is help pressed on the arrow or on the bar. It generates the
@@ -196,13 +202,23 @@ void wxScrollBar::SetScrollbar(int position, int thumbSize,
int range, int pageSize, int range, int pageSize,
bool refresh) bool refresh)
{ {
// we only refresh everythign when the range changes, thumb position
// changes are handled in OnIdle
bool needsRefresh = (range != m_range) ||
(thumbSize != m_thumbSize) ||
(pageSize != m_pageSize);
// set all parameters // set all parameters
m_range = range; m_range = range;
m_thumbSize = thumbSize; m_thumbSize = thumbSize;
SetThumbPosition(position); SetThumbPosition(position);
m_pageSize = pageSize; m_pageSize = pageSize;
if ( refresh ) // ignore refresh parameter unless we really need to refresh everything -
// there ir a lot of existing code which just calls SetScrollbar() without
// specifying the last parameter even though it doesn't need at all to
// refresh the window immediately
if ( refresh && needsRefresh )
{ {
// and update the window // and update the window
Refresh(); Refresh();
@@ -271,6 +287,23 @@ void wxScrollBar::OnIdle(wxIdleEvent& event)
#endif // 0/1 #endif // 0/1
} }
#ifdef WXDEBUG_SCROLLBAR
static bool s_refreshDebug = FALSE;
if ( s_refreshDebug )
{
wxClientDC dc(this);
dc.SetBrush(*wxCYAN_BRUSH);
dc.SetPen(*wxTRANSPARENT_PEN);
dc.DrawRectangle(rect);
// under Unix we use "--sync" X option for this
#ifdef __WXMSW__
::GdiFlush();
::Sleep(200);
#endif // __WXMSW__
}
#endif // WXDEBUG_SCROLLBAR
Refresh(TRUE, &rect); Refresh(TRUE, &rect);
} }

View File

@@ -64,6 +64,11 @@
// turn wxTextCtrl::Replace() debugging on (very inefficient!) // turn wxTextCtrl::Replace() debugging on (very inefficient!)
#define WXDEBUG_TEXT_REPLACE #define WXDEBUG_TEXT_REPLACE
#ifndef __WXDEBUG__
#undef WXDEBUG_TEXT
#undef WXDEBUG_TEXT_REPLACE
#endif
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// private functions // private functions
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -1427,6 +1432,13 @@ void wxTextCtrl::OnSize(wxSizeEvent& event)
event.Skip(); event.Skip();
} }
wxCoord wxTextCtrl::GetTotalWidth() const
{
wxCoord w;
CalcUnscrolledPosition(m_rectText.width, 0, &w, NULL);
return w;
}
wxCoord wxTextCtrl::GetTextWidth(const wxString& text) const wxCoord wxTextCtrl::GetTextWidth(const wxString& text) const
{ {
wxCoord w; wxCoord w;
@@ -1984,7 +1996,7 @@ void wxTextCtrl::RefreshPixelRange(long line, wxCoord start, wxCoord width)
if ( width == 0 ) if ( width == 0 )
{ {
// till the end of line // till the end of line
rect.width = m_rectText.width - rect.x; rect.width = GetTotalWidth() - rect.x;
} }
else else
{ {

View File

@@ -41,6 +41,13 @@
#include "wx/univ/renderer.h" #include "wx/univ/renderer.h"
#include "wx/univ/theme.h" #include "wx/univ/theme.h"
// turn Refresh() debugging on/off
#define WXDEBUG_REFRESH
#ifndef __WXDEBUG__
#undef WXDEBUG_REFRESH
#endif
// ============================================================================ // ============================================================================
// implementation // implementation
// ============================================================================ // ============================================================================
@@ -278,28 +285,51 @@ void wxWindow::DoDraw(wxControlRenderer *renderer)
void wxWindow::Refresh(bool eraseBackground, const wxRect *rectClient) void wxWindow::Refresh(bool eraseBackground, const wxRect *rectClient)
{ {
wxRect rectWin;
wxPoint pt = GetClientAreaOrigin();
wxSize size = GetClientSize();
if ( rectClient ) if ( rectClient )
{ {
wxRect rectWin = *rectClient; rectWin = *rectClient;
rectWin.Offset(GetClientAreaOrigin());
wxWindowNative::Refresh(eraseBackground, &rectWin); // don't refresh anything beyond the client area (scrollbars for
// example)
if ( rectWin.GetRight() > size.x )
rectWin.SetRight(size.x);
if ( rectWin.GetBottom() > size.y )
rectWin.SetBottom(size.y);
// debugging helper rectWin.Offset(pt);
#if 0 }
else // refresh the entire client area
{
rectWin.x = pt.x;
rectWin.y = pt.y;
rectWin.width = size.x;
rectWin.height = size.y;
}
wxWindowNative::Refresh(eraseBackground, &rectWin);
// debugging helper
#ifdef WXDEBUG_REFRESH
static bool s_refreshDebug = FALSE;
if ( s_refreshDebug )
{
wxWindowDC dc(this); wxWindowDC dc(this);
dc.SetBrush(*wxBLUE_BRUSH); dc.SetBrush(*wxCYAN_BRUSH);
dc.SetPen(*wxTRANSPARENT_PEN); dc.SetPen(*wxTRANSPARENT_PEN);
dc.DrawRectangle(rectWin); dc.DrawRectangle(rectWin);
::GdiFlush(); // under Unix we use "--sync" X option for this
::Sleep(1000); #ifdef __WXMSW__
#endif // 0 ::GdiFlush();
} ::Sleep(200);
else #endif // __WXMSW__
{
wxWindowNative::Refresh(eraseBackground);
} }
#endif // WXDEBUG_REFRESH
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -498,6 +528,15 @@ void wxWindow::DoSetClientSize(int width, int height)
// window class // window class
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void wxWindow::RefreshScrollbars()
{
if ( m_scrollbarHorz )
m_scrollbarHorz->Refresh();
if ( m_scrollbarVert )
m_scrollbarVert->Refresh();
}
void wxWindow::PositionScrollbars() void wxWindow::PositionScrollbars()
{ {
// do not use GetClientSize/Rect as it relies on the scrollbars being // do not use GetClientSize/Rect as it relies on the scrollbars being
@@ -543,6 +582,8 @@ void wxWindow::PositionScrollbars()
m_scrollbarHorz->SetSize(rectBar, wxSIZE_NO_ADJUSTMENTS); m_scrollbarHorz->SetSize(rectBar, wxSIZE_NO_ADJUSTMENTS);
} }
RefreshScrollbars();
} }
void wxWindow::SetScrollbar(int orient, void wxWindow::SetScrollbar(int orient,
@@ -582,9 +623,10 @@ void wxWindow::SetScrollbar(int orient,
{ {
if ( GetWindowStyle() & wxALWAYS_SHOW_SB ) if ( GetWindowStyle() & wxALWAYS_SHOW_SB )
{ {
// just disable the scrollbar
scrollbar->Disable(); scrollbar->Disable();
} }
else else // really remove the scrollbar
{ {
delete scrollbar; delete scrollbar;
@@ -592,6 +634,12 @@ void wxWindow::SetScrollbar(int orient,
m_scrollbarVert = NULL; m_scrollbarVert = NULL;
else else
m_scrollbarHorz = NULL; m_scrollbarHorz = NULL;
// the size of the remaining scrollbar must be adjusted
if ( m_scrollbarHorz || m_scrollbarVert )
{
PositionScrollbars();
}
} }
} }
} }
@@ -679,7 +727,7 @@ wxRect wxWindow::ScrollNoRefresh(int dx, int dy, const wxRect *rectTotal)
// just redraw everything as nothing of the displayed image will stay // just redraw everything as nothing of the displayed image will stay
wxLogTrace(_T("scroll"), _T("refreshing everything")); wxLogTrace(_T("scroll"), _T("refreshing everything"));
rect = rectTotal ? *rectTotal : GetClientRect(); rect = rectTotal ? *rectTotal : wxRect(0, 0, sizeTotal.x, sizeTotal.y);
} }
else // move the part which doesn't change to the new location else // move the part which doesn't change to the new location
{ {