added wxGridUpdateLocker helper class wrapping Begin/EndBatch() calls in a more convenient and safe way

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@44833 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2007-03-15 17:25:15 +00:00
parent 7660b85c31
commit b62f94ff48
8 changed files with 143 additions and 19 deletions

View File

@@ -39,6 +39,7 @@ All:
- Fixed crashes in helpview when opening a file. - Fixed crashes in helpview when opening a file.
- Added wxMutex::LockTimeout() (Aleksandr Napylov) - Added wxMutex::LockTimeout() (Aleksandr Napylov)
- Set locale to the default in all ports, not just wxGTK - Set locale to the default in all ports, not just wxGTK
- Added wxGridUpdateLocker helper class (Evgeniy Tarassov)
wxGTK: wxGTK:

View File

@@ -188,6 +188,7 @@
\input gridrend.tex \input gridrend.tex
\input gridtbl.tex \input gridtbl.tex
\input gridsizr.tex \input gridsizr.tex
\input gupdlock.tex
\input hashmap.tex \input hashmap.tex
\input hashset.tex \input hashset.tex
\input hash.tex \input hash.tex

View File

@@ -253,6 +253,10 @@ the grid is suppressed. Each call to BeginBatch must be matched by a later call
modification can be enclosed between BeginBatch and EndBatch calls to avoid modification can be enclosed between BeginBatch and EndBatch calls to avoid
screen flicker. The final EndBatch will cause the grid to be repainted. screen flicker. The final EndBatch will cause the grid to be repainted.
\wxheading{See also}
\helpref{wxGridUpdateLocker}{wxgridupdatelocker}
\membersection{wxGrid::BlockToDeviceRect}\label{wxgridblocktodevicerect} \membersection{wxGrid::BlockToDeviceRect}\label{wxgridblocktodevicerect}
@@ -514,6 +518,10 @@ EndBatch. Code that does a lot of grid modification can be enclosed between
BeginBatch and EndBatch calls to avoid screen flicker. The final EndBatch will BeginBatch and EndBatch calls to avoid screen flicker. The final EndBatch will
cause the grid to be repainted. cause the grid to be repainted.
\wxheading{See also}
\helpref{wxGridUpdateLocker}{wxgridupdatelocker}
\membersection{wxGrid::Fit}\label{wxgridfit} \membersection{wxGrid::Fit}\label{wxgridfit}

View File

@@ -0,0 +1,81 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Name: gupdlock.tex
%% Purpose: wxGridUpdateLocker documentation
%% Author: Evgeniy Tarassov
%% Created: 2007-03-15
%% RCS-ID: $Id$
%% Copyright: (c) 2007 TT-Solutions SARL
%% License: wxWindows license
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{\class{wxGridUpdateLocker}}\label{wxgridupdatelocker}
This small class can be used to prevent \helpref{wxGrid}{wxgrid} from redrawing
during its lifetime by calling \helpref{wxGrid::BeginBatch}{wxgridbeginbatch}
in its constructor and \helpref{wxGrid::EndBatch}{wxgridendbatch} in its
destructor. It is typically used in a function performing several operations
with a grid which would otherwise result in flicker. For example:
{\small
\begin{verbatim}
void MyFrame::Foo()
{
m_grid = new wxGrid(this, ...);
wxGridUpdateLocker noUpdates(m_grid);
m_grid->AppendColumn();
... many other operations with m_grid...
m_grid->AppendRow();
// destructor called, grid refreshed
}
\end{verbatim}
}
Using this class is easier and safer than calling
\helpref{BeginBatch}{wxgridbeginbatch} and \helpref{EndBatch}{wxgridendbatch}
because you don't risk not to call the latter (due to an exception for example).
\wxheading{Derived from}
None.
\wxheading{Include files}
<wx/grid.h>
\latexignore{\rtfignore{\wxheading{Members}}}
\membersection{wxGridUpdateLocker::wxGridUpdateLocker}\label{wxgridupdatelockerctor}
\func{}{wxGridUpdateLocker}{\param{wxGrid *}{grid = \NULL}}
Creates an object preventing the updates of the specified \arg{grid}. The
parameter could be \NULL in which case nothing is done. If \arg{grid} is
non-\NULL then the grid must exist for longer than wxGridUpdateLocker object
itself.
The default constructor could be followed by a call to
\helpref{wxGridUpdateLocker::Create}{wxgridupdatelockercreate} to set the
grid object later.
\membersection{wxGridUpdateLocker::\destruct{wxGridUpdateLocker}}\label{wxgridupdatelockerdtor}
\func{}{\destruct{wxGridUpdateLocker}}{\void}
Destructor reenables updates for the grid this object is associated with.
\membersection{wxGridUpdateLocker::Create}\label{wxgridupdatelockercreate}
\func{void}{Create}{\param{wxGrid* }{grid}}
This method can be called if the object had been constructed using the default
constructor. It must not be called more than once.

View File

@@ -2007,6 +2007,47 @@ protected:
}; };
// ----------------------------------------------------------------------------
// wxGridUpdateLocker prevents updates to a grid during its lifetime
// ----------------------------------------------------------------------------
class WXDLLIMPEXP_ADV wxGridUpdateLocker
{
public:
// if the pointer is NULL, Create() can be called later
wxGridUpdateLocker(wxGrid *grid = NULL)
{
Init(grid);
}
// can be called if ctor was used with a NULL pointer, must not be called
// more than once
void Create(wxGrid *grid)
{
wxASSERT_MSG( !m_grid, _T("shouldn't be called more than once") );
Init(grid);
}
~wxGridUpdateLocker()
{
if ( m_grid )
m_grid->EndBatch();
}
private:
void Init(wxGrid *grid)
{
m_grid = grid;
if ( m_grid )
m_grid->BeginBatch();
}
wxGrid *m_grid;
DECLARE_NO_COPY_CLASS(wxGridUpdateLocker)
};
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Grid event class and event types // Grid event class and event types
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -668,7 +668,7 @@ void GridFrame::DeleteSelectedRows( wxCommandEvent& WXUNUSED(ev) )
{ {
if ( grid->IsSelection() ) if ( grid->IsSelection() )
{ {
grid->BeginBatch(); wxGridUpdateLocker locker(grid);
for ( int n = 0; n < grid->GetNumberRows(); ) for ( int n = 0; n < grid->GetNumberRows(); )
{ {
if ( grid->IsInSelection( n , 0 ) ) if ( grid->IsInSelection( n , 0 ) )
@@ -676,7 +676,6 @@ void GridFrame::DeleteSelectedRows( wxCommandEvent& WXUNUSED(ev) )
else else
n++; n++;
} }
grid->EndBatch();
} }
} }
@@ -685,7 +684,7 @@ void GridFrame::DeleteSelectedCols( wxCommandEvent& WXUNUSED(ev) )
{ {
if ( grid->IsSelection() ) if ( grid->IsSelection() )
{ {
grid->BeginBatch(); wxGridUpdateLocker locker(grid);
for ( int n = 0; n < grid->GetNumberCols(); ) for ( int n = 0; n < grid->GetNumberCols(); )
{ {
if ( grid->IsInSelection( 0 , n ) ) if ( grid->IsInSelection( 0 , n ) )
@@ -693,7 +692,6 @@ void GridFrame::DeleteSelectedCols( wxCommandEvent& WXUNUSED(ev) )
else else
n++; n++;
} }
grid->EndBatch();
} }
} }

View File

@@ -203,11 +203,12 @@ bool wxDbGridTableBase::AssignDbTable(wxDbTable *tab, int count, bool takeOwners
{ {
wxDbGridCellAttrProvider *provider; wxDbGridCellAttrProvider *provider;
wxGridUpdateLocker locker(GetView());
//Remove Information from grid about old data //Remove Information from grid about old data
if (GetView()) if (GetView())
{ {
wxGrid *grid = GetView(); wxGrid *grid = GetView();
grid->BeginBatch();
grid->ClearSelection(); grid->ClearSelection();
if (grid->IsCellEditControlEnabled()) if (grid->IsCellEditControlEnabled())
{ {
@@ -250,7 +251,6 @@ bool wxDbGridTableBase::AssignDbTable(wxDbTable *tab, int count, bool takeOwners
wxGrid * grid = GetView(); wxGrid * grid = GetView();
wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_rowtotal); wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, m_rowtotal);
grid->ProcessTableMessage(msg); grid->ProcessTableMessage(msg);
grid->EndBatch();
} }
m_dbowner = takeOwnership; m_dbowner = takeOwnership;
m_rowmodified = false; m_rowmodified = false;

View File

@@ -10595,8 +10595,9 @@ int wxGrid::SetOrCalcColumnSizes(bool calcOnly, bool setAsMin)
{ {
int width = m_rowLabelWidth; int width = m_rowLabelWidth;
if ( !calcOnly ) wxGridUpdateLocker locker;
BeginBatch(); if(!calcOnly)
locker.Create(this);
for ( int col = 0; col < m_numCols; col++ ) for ( int col = 0; col < m_numCols; col++ )
{ {
@@ -10606,9 +10607,6 @@ int wxGrid::SetOrCalcColumnSizes(bool calcOnly, bool setAsMin)
width += GetColWidth(col); width += GetColWidth(col);
} }
if ( !calcOnly )
EndBatch();
return width; return width;
} }
@@ -10616,8 +10614,9 @@ int wxGrid::SetOrCalcRowSizes(bool calcOnly, bool setAsMin)
{ {
int height = m_colLabelHeight; int height = m_colLabelHeight;
if ( !calcOnly ) wxGridUpdateLocker locker;
BeginBatch(); if(!calcOnly)
locker.Create(this);
for ( int row = 0; row < m_numRows; row++ ) for ( int row = 0; row < m_numRows; row++ )
{ {
@@ -10627,15 +10626,12 @@ int wxGrid::SetOrCalcRowSizes(bool calcOnly, bool setAsMin)
height += GetRowHeight(row); height += GetRowHeight(row);
} }
if ( !calcOnly )
EndBatch();
return height; return height;
} }
void wxGrid::AutoSize() void wxGrid::AutoSize()
{ {
BeginBatch(); wxGridUpdateLocker locker(this);
// we need to round up the size of the scrollable area to a multiple of // we need to round up the size of the scrollable area to a multiple of
// scroll step to ensure that we don't get the scrollbars when we're sized // scroll step to ensure that we don't get the scrollbars when we're sized
@@ -10701,8 +10697,6 @@ void wxGrid::AutoSize()
// client size but also leave space for (not needed any more) scrollbars // client size but also leave space for (not needed any more) scrollbars
SetScrollbars(0, 0, 0, 0, 0, 0, true); SetScrollbars(0, 0, 0, 0, 0, 0, true);
SetClientSize(sizeFit.x + m_rowLabelWidth, sizeFit.y + m_colLabelHeight); SetClientSize(sizeFit.x + m_rowLabelWidth, sizeFit.y + m_colLabelHeight);
EndBatch();
} }
void wxGrid::AutoSizeRowLabelSize( int row ) void wxGrid::AutoSizeRowLabelSize( int row )