use YieldFor() in wxTopLevelWindowGTK::RequestUserAttention; comment on the use of YieldFor() in wxProgressDialog; add some TODOs near wxYieldIfNeeded()/wxSafeYield() calls in wxListCtrl, wxDataViewCtrl, wxTreeCtrl (closes #10320)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@58916 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Francesco Montorsi
2009-02-15 15:42:15 +00:00
parent 31cb01131e
commit 977a41ec3e
5 changed files with 254 additions and 234 deletions

View File

@@ -189,7 +189,7 @@ private:
{ {
wxDataViewCtrl * const owner = GetOwner(); wxDataViewCtrl * const owner = GetOwner();
owner->ColumnMoved(owner->GetColumn(event.GetColumn()), owner->ColumnMoved(owner->GetColumn(event.GetColumn()),
event.GetNewOrder()); event.GetNewOrder());
} }
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
@@ -543,8 +543,8 @@ private:
// for double click logic // for double click logic
unsigned int m_lineLastClicked, unsigned int m_lineLastClicked,
m_lineBeforeLastClicked, m_lineBeforeLastClicked,
m_lineSelectSingleOnUp; m_lineSelectSingleOnUp;
// the pen used to draw horiz/vertical rules // the pen used to draw horiz/vertical rules
wxPen m_penRule; wxPen m_penRule;
@@ -583,7 +583,7 @@ public:
virtual bool Cleared() virtual bool Cleared()
{ return m_mainWindow->Cleared(); } { return m_mainWindow->Cleared(); }
virtual void Resort() virtual void Resort()
{ m_mainWindow->Resort(); } { m_mainWindow->Resort(); }
wxDataViewMainWindow *m_mainWindow; wxDataViewMainWindow *m_mainWindow;
}; };
@@ -641,7 +641,7 @@ int wxDataViewRenderer::CalculateAlignment() const
if (m_align == wxDVR_DEFAULT_ALIGNMENT) if (m_align == wxDVR_DEFAULT_ALIGNMENT)
{ {
if (GetOwner() == NULL) if (GetOwner() == NULL)
return wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL; return wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL;
return GetOwner()->GetAlignment() | wxALIGN_CENTRE_VERTICAL; return GetOwner()->GetAlignment() | wxALIGN_CENTRE_VERTICAL;
} }
@@ -656,7 +656,7 @@ int wxDataViewRenderer::CalculateAlignment() const
IMPLEMENT_ABSTRACT_CLASS(wxDataViewCustomRenderer, wxDataViewRenderer) IMPLEMENT_ABSTRACT_CLASS(wxDataViewCustomRenderer, wxDataViewRenderer)
wxDataViewCustomRenderer::wxDataViewCustomRenderer( const wxString &varianttype, wxDataViewCustomRenderer::wxDataViewCustomRenderer( const wxString &varianttype,
wxDataViewCellMode mode, int align ) : wxDataViewCellMode mode, int align ) :
wxDataViewRenderer( varianttype, mode, align ) wxDataViewRenderer( varianttype, mode, align )
{ {
} }
@@ -704,8 +704,8 @@ wxControl* wxDataViewTextRenderer::CreateEditorCtrl( wxWindow *parent,
wxRect labelRect, const wxVariant &value ) wxRect labelRect, const wxVariant &value )
{ {
return new wxTextCtrl( parent, wxID_ANY, value, return new wxTextCtrl( parent, wxID_ANY, value,
wxPoint(labelRect.x,labelRect.y), wxPoint(labelRect.x,labelRect.y),
wxSize(labelRect.width,labelRect.height) ); wxSize(labelRect.width,labelRect.height) );
} }
bool wxDataViewTextRenderer::GetValueFromEditorCtrl( wxControl *editor, wxVariant &value ) bool wxDataViewTextRenderer::GetValueFromEditorCtrl( wxControl *editor, wxVariant &value )
@@ -761,13 +761,13 @@ bool wxDataViewTextRendererAttr::Render( wxRect cell, wxDC *dc, int WXUNUSED(sta
if (m_attr.GetBold() || m_attr.GetItalic()) if (m_attr.GetBold() || m_attr.GetItalic())
{ {
font = dc->GetFont(); font = dc->GetFont();
wxFont myfont = font; wxFont myfont = font;
if (m_attr.GetBold()) if (m_attr.GetBold())
myfont.SetWeight( wxFONTWEIGHT_BOLD ); myfont.SetWeight( wxFONTWEIGHT_BOLD );
if (m_attr.GetItalic()) if (m_attr.GetItalic())
myfont.SetStyle( wxFONTSTYLE_ITALIC ); myfont.SetStyle( wxFONTSTYLE_ITALIC );
dc->SetFont( myfont ); dc->SetFont( myfont );
} }
} }
@@ -885,8 +885,8 @@ bool wxDataViewToggleRenderer::Render( wxRect cell, wxDC *dc, int WXUNUSED(state
} }
bool wxDataViewToggleRenderer::Activate( wxRect WXUNUSED(cell), bool wxDataViewToggleRenderer::Activate( wxRect WXUNUSED(cell),
wxDataViewModel *model, wxDataViewModel *model,
const wxDataViewItem & item, unsigned int col) const wxDataViewItem & item, unsigned int col)
{ {
bool value = !m_toggle; bool value = !m_toggle;
wxVariant variant = value; wxVariant variant = value;
@@ -1049,7 +1049,7 @@ wxSize wxDataViewDateRenderer::GetSize() const
} }
bool wxDataViewDateRenderer::Activate( wxRect WXUNUSED(cell), wxDataViewModel *model, bool wxDataViewDateRenderer::Activate( wxRect WXUNUSED(cell), wxDataViewModel *model,
const wxDataViewItem & item, unsigned int col ) const wxDataViewItem & item, unsigned int col )
{ {
wxVariant variant; wxVariant variant;
model->GetValue( variant, item, col ); model->GetValue( variant, item, col );
@@ -1075,7 +1075,7 @@ bool wxDataViewDateRenderer::Activate( wxRect WXUNUSED(cell), wxDataViewModel *m
IMPLEMENT_CLASS(wxDataViewIconTextRenderer, wxDataViewCustomRenderer) IMPLEMENT_CLASS(wxDataViewIconTextRenderer, wxDataViewCustomRenderer)
wxDataViewIconTextRenderer::wxDataViewIconTextRenderer( wxDataViewIconTextRenderer::wxDataViewIconTextRenderer(
const wxString &varianttype, wxDataViewCellMode mode, int align ) : const wxString &varianttype, wxDataViewCellMode mode, int align ) :
wxDataViewCustomRenderer( varianttype, mode, align ) wxDataViewCustomRenderer( varianttype, mode, align )
{ {
SetMode(mode); SetMode(mode);
@@ -1129,15 +1129,15 @@ wxSize wxDataViewIconTextRenderer::GetSize() const
wxControl * wxControl *
wxDataViewIconTextRenderer::CreateEditorCtrl(wxWindow * WXUNUSED(parent), wxDataViewIconTextRenderer::CreateEditorCtrl(wxWindow * WXUNUSED(parent),
wxRect WXUNUSED(labelRect), wxRect WXUNUSED(labelRect),
const wxVariant& WXUNUSED(value)) const wxVariant& WXUNUSED(value))
{ {
return NULL; return NULL;
} }
bool bool
wxDataViewIconTextRenderer::GetValueFromEditorCtrl(wxControl* WXUNUSED(editor), wxDataViewIconTextRenderer::GetValueFromEditorCtrl(wxControl* WXUNUSED(editor),
wxVariant& WXUNUSED(value)) wxVariant& WXUNUSED(value))
{ {
return false; return false;
} }
@@ -1152,7 +1152,7 @@ class wxBitmapCanvas: public wxWindow
{ {
public: public:
wxBitmapCanvas( wxWindow *parent, const wxBitmap &bitmap, const wxSize &size ) : wxBitmapCanvas( wxWindow *parent, const wxBitmap &bitmap, const wxSize &size ) :
wxWindow( parent, wxID_ANY, wxPoint(0,0), size ) wxWindow( parent, wxID_ANY, wxPoint(0,0), size )
{ {
m_bitmap = bitmap; m_bitmap = bitmap;
Connect( wxEVT_PAINT, wxPaintEventHandler(wxBitmapCanvas::OnPaint) ); Connect( wxEVT_PAINT, wxPaintEventHandler(wxBitmapCanvas::OnPaint) );
@@ -1171,7 +1171,7 @@ class wxDataViewDropSource: public wxDropSource
{ {
public: public:
wxDataViewDropSource( wxDataViewMainWindow *win, unsigned int row ) : wxDataViewDropSource( wxDataViewMainWindow *win, unsigned int row ) :
wxDropSource( win ) wxDropSource( win )
{ {
m_win = win; m_win = win;
m_row = row; m_row = row;
@@ -1200,12 +1200,12 @@ public:
wxBitmap ib = m_win->CreateItemBitmap( m_row, indent ); wxBitmap ib = m_win->CreateItemBitmap( m_row, indent );
m_dist_x -= indent; m_dist_x -= indent;
m_hint = new wxFrame( m_win->GetParent(), wxID_ANY, wxEmptyString, m_hint = new wxFrame( m_win->GetParent(), wxID_ANY, wxEmptyString,
wxPoint(pos.x - m_dist_x, pos.y + 5 ), wxPoint(pos.x - m_dist_x, pos.y + 5 ),
ib.GetSize(), ib.GetSize(),
wxFRAME_TOOL_WINDOW | wxFRAME_TOOL_WINDOW |
wxFRAME_FLOAT_ON_PARENT | wxFRAME_FLOAT_ON_PARENT |
wxFRAME_NO_TASKBAR | wxFRAME_NO_TASKBAR |
wxNO_BORDER ); wxNO_BORDER );
new wxBitmapCanvas( m_hint, ib, ib.GetSize() ); new wxBitmapCanvas( m_hint, ib, ib.GetSize() );
m_hint->Show(); m_hint->Show();
} }
@@ -1236,28 +1236,28 @@ public:
virtual wxDragResult OnDragOver( wxCoord x, wxCoord y, wxDragResult def ) virtual wxDragResult OnDragOver( wxCoord x, wxCoord y, wxDragResult def )
{ {
wxDataFormat format = GetMatchingPair(); wxDataFormat format = GetMatchingPair();
if (format == wxDF_INVALID) if (format == wxDF_INVALID)
return wxDragNone; return wxDragNone;
return m_win->OnDragOver( format, x, y, def); return m_win->OnDragOver( format, x, y, def);
} }
virtual bool OnDrop( wxCoord x, wxCoord y ) virtual bool OnDrop( wxCoord x, wxCoord y )
{ {
wxDataFormat format = GetMatchingPair(); wxDataFormat format = GetMatchingPair();
if (format == wxDF_INVALID) if (format == wxDF_INVALID)
return false; return false;
return m_win->OnDrop( format, x, y ); return m_win->OnDrop( format, x, y );
} }
virtual wxDragResult OnData( wxCoord x, wxCoord y, wxDragResult def ) virtual wxDragResult OnData( wxCoord x, wxCoord y, wxDragResult def )
{ {
wxDataFormat format = GetMatchingPair(); wxDataFormat format = GetMatchingPair();
if (format == wxDF_INVALID) if (format == wxDF_INVALID)
return wxDragNone; return wxDragNone;
if (!GetData()) if (!GetData())
return wxDragNone; return wxDragNone;
return m_win->OnData( format, x, y, def ); return m_win->OnData( format, x, y, def );
} }
virtual void OnLeave() virtual void OnLeave()
@@ -1527,8 +1527,8 @@ wxBitmap wxDataViewMainWindow::CreateItemBitmap( unsigned int row, int &indent )
indent = GetOwner()->GetIndent() * node->GetIndentLevel(); indent = GetOwner()->GetIndent() * node->GetIndentLevel();
indent = indent + m_lineHeight; //try to use the m_lineHeight as the expander space indent = indent + m_lineHeight; //try to use the m_lineHeight as the expander space
if(!node->HasChildren()) if(!node->HasChildren())
delete node; delete node;
} }
width -= indent; width -= indent;
@@ -1641,7 +1641,7 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
unsigned int item_start = GetLineAt( wxMax(0,update.y) ); unsigned int item_start = GetLineAt( wxMax(0,update.y) );
unsigned int item_count = unsigned int item_count =
wxMin( (int)( GetLineAt( wxMax(0,update.y+update.height) ) - item_start + 1), wxMin( (int)( GetLineAt( wxMax(0,update.y+update.height) ) - item_start + 1),
(int)(GetRowCount( ) - item_start)); (int)(GetRowCount( ) - item_start));
unsigned int item_last = item_start + item_count; unsigned int item_last = item_start + item_count;
// compute which columns needs to be redrawn // compute which columns needs to be redrawn
@@ -1739,7 +1739,7 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
if (m_dropHint) if (m_dropHint)
{ {
wxRect rect( x_start, GetLineStart( m_dropHintLine ), wxRect rect( x_start, GetLineStart( m_dropHintLine ),
x_last, GetLineHeight( m_dropHintLine ) ); x_last, GetLineHeight( m_dropHintLine ) );
dc.SetPen( *wxBLACK_PEN ); dc.SetPen( *wxBLACK_PEN );
dc.SetBrush( *wxTRANSPARENT_BRUSH ); dc.SetBrush( *wxTRANSPARENT_BRUSH );
dc.DrawRectangle( rect ); dc.DrawRectangle( rect );
@@ -1835,8 +1835,8 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
else else
wxRendererNative::Get().DrawTreeItemButton( this, dc, rect, flag); wxRendererNative::Get().DrawTreeItemButton( this, dc, rect, flag);
} }
//force the expander column to left-center align //force the expander column to left-center align
cell->SetAlignment( wxALIGN_CENTER_VERTICAL ); cell->SetAlignment( wxALIGN_CENTER_VERTICAL );
} }
if (node && !node->HasChildren()) if (node && !node->HasChildren())
{ {
@@ -1903,7 +1903,11 @@ void wxDataViewMainWindow::OnRenameTimer()
// We have to call this here because changes may just have // We have to call this here because changes may just have
// been made and no screen update taken place. // been made and no screen update taken place.
if ( m_dirty ) if ( m_dirty )
{
// TODO: use wxTheApp->SafeYieldFor(NULL, wxEVT_CATEGORY_UI) instead
// (needs to be tested!)
wxSafeYield(); wxSafeYield();
}
int xpos = 0; int xpos = 0;
unsigned int cols = GetOwner()->GetColumnCount(); unsigned int cols = GetOwner()->GetColumnCount();
@@ -1919,26 +1923,26 @@ void wxDataViewMainWindow::OnRenameTimer()
xpos += c->GetWidth(); xpos += c->GetWidth();
} }
// we have to take an expander column into account and compute its indentation // we have to take an expander column into account and compute its indentation
// to get the editor at the correct x position where the actual text is // to get the editor at the correct x position where the actual text is
int indent = 0; int indent = 0;
if (!IsVirtualList() && GetOwner()->GetExpanderColumn() == m_currentCol) if (!IsVirtualList() && GetOwner()->GetExpanderColumn() == m_currentCol)
{ {
wxDataViewTreeNode* node = GetTreeNodeByRow(m_currentRow); wxDataViewTreeNode* node = GetTreeNodeByRow(m_currentRow);
indent = GetOwner()->GetIndent() * node->GetIndentLevel(); indent = GetOwner()->GetIndent() * node->GetIndentLevel();
indent = indent + m_lineHeight; indent = indent + m_lineHeight;
if(!node->HasChildren()) if(!node->HasChildren())
delete node; delete node;
} }
wxRect labelRect( xpos + indent, wxRect labelRect( xpos + indent,
GetLineStart( m_currentRow ), GetLineStart( m_currentRow ),
m_currentCol->GetWidth() - indent, m_currentCol->GetWidth() - indent,
GetLineHeight( m_currentRow ) ); GetLineHeight( m_currentRow ) );
GetOwner()->CalcScrolledPosition( labelRect.x, labelRect.y, GetOwner()->CalcScrolledPosition( labelRect.x, labelRect.y,
&labelRect.x, &labelRect.y); &labelRect.x, &labelRect.y);
wxDataViewItem item = GetItemByRow( m_currentRow ); wxDataViewItem item = GetItemByRow( m_currentRow );
m_currentCol->GetRenderer()->StartEditing( item, labelRect ); m_currentCol->GetRenderer()->StartEditing( item, labelRect );
@@ -2006,7 +2010,7 @@ bool Walker( wxDataViewTreeNode * node, DoJob & func )
continue; continue;
case DoJob::CONT: case DoJob::CONT:
default: default:
; ;
} }
} }
return false; return false;
@@ -2052,7 +2056,7 @@ bool wxDataViewMainWindow::ItemAdded(const wxDataViewItem & parent, const wxData
static void DestroyTreeHelper( wxDataViewTreeNode * node); static void DestroyTreeHelper( wxDataViewTreeNode * node);
bool wxDataViewMainWindow::ItemDeleted(const wxDataViewItem& parent, bool wxDataViewMainWindow::ItemDeleted(const wxDataViewItem& parent,
const wxDataViewItem& item) const wxDataViewItem& item)
{ {
if (!m_root) if (!m_root)
{ {
@@ -2290,7 +2294,7 @@ unsigned int wxDataViewMainWindow::GetLastVisibleRow()
{ {
wxSize client_size = GetClientSize(); wxSize client_size = GetClientSize();
m_owner->CalcUnscrolledPosition( client_size.x, client_size.y, m_owner->CalcUnscrolledPosition( client_size.x, client_size.y,
&client_size.x, &client_size.y ); &client_size.x, &client_size.y );
//we should deal with the pixel here //we should deal with the pixel here
unsigned int row = GetLineAt(client_size.y) - 1; unsigned int row = GetLineAt(client_size.y) - 1;
@@ -2471,7 +2475,7 @@ void wxDataViewMainWindow::RefreshRowsAfter( unsigned int firstRow )
void wxDataViewMainWindow::OnArrowChar(unsigned int newCurrent, const wxKeyEvent& event) void wxDataViewMainWindow::OnArrowChar(unsigned int newCurrent, const wxKeyEvent& event)
{ {
wxCHECK_RET( newCurrent < GetRowCount(), wxCHECK_RET( newCurrent < GetRowCount(),
_T("invalid item index in OnArrowChar()") ); _T("invalid item index in OnArrowChar()") );
// if there is no selection, we cannot move it anywhere // if there is no selection, we cannot move it anywhere
if (!HasCurrentRow()) if (!HasCurrentRow())
@@ -2601,14 +2605,14 @@ int wxDataViewMainWindow::GetLineAt( unsigned int y ) const
unsigned int yy = 0; unsigned int yy = 0;
for (;;) for (;;)
{ {
const wxDataViewTreeNode* node = GetTreeNodeByRow(row); const wxDataViewTreeNode* node = GetTreeNodeByRow(row);
if (!node) if (!node)
{ {
// not really correct... // not really correct...
return row + ((y-yy) / m_lineHeight); return row + ((y-yy) / m_lineHeight);
} }
wxDataViewItem item = node->GetItem(); wxDataViewItem item = node->GetItem();
if (node && !node->HasChildren()) if (node && !node->HasChildren())
{ {
@@ -2617,11 +2621,11 @@ int wxDataViewMainWindow::GetLineAt( unsigned int y ) const
wxDELETE(node); wxDELETE(node);
} }
unsigned int cols = GetOwner()->GetColumnCount(); unsigned int cols = GetOwner()->GetColumnCount();
unsigned int col; unsigned int col;
int height = m_lineHeight; int height = m_lineHeight;
for (col = 0; col < cols; col++) for (col = 0; col < cols; col++)
{ {
const wxDataViewColumn *column = GetOwner()->GetColumn(col); const wxDataViewColumn *column = GetOwner()->GetColumn(col);
if (column->IsHidden()) if (column->IsHidden())
continue; // skip it! continue; // skip it!
@@ -2635,13 +2639,13 @@ int wxDataViewMainWindow::GetLineAt( unsigned int y ) const
wxDataViewRenderer *renderer2 = const_cast<wxDataViewRenderer*>(renderer); wxDataViewRenderer *renderer2 = const_cast<wxDataViewRenderer*>(renderer);
renderer2->SetValue( value ); renderer2->SetValue( value );
height = wxMax( height, renderer->GetSize().y ); height = wxMax( height, renderer->GetSize().y );
} }
yy += height; yy += height;
if (y < yy) if (y < yy)
return row; return row;
row++; row++;
} }
} }
@@ -2663,7 +2667,7 @@ int wxDataViewMainWindow::GetLineHeight( unsigned int row ) const
{ {
// Yes, if the node does not have any child, it must be a leaf which // Yes, if the node does not have any child, it must be a leaf which
// mean that it is a temporarily created by GetTreeNodeByRow // mean that it is a temporarily created by GetTreeNodeByRow
wxDELETE(node); wxDELETE(node);
} }
int height = m_lineHeight; int height = m_lineHeight;
@@ -2705,7 +2709,7 @@ public:
{ {
current ++; current ++;
if( current == static_cast<int>(row)) if( current == static_cast<int>(row))
{ {
ret = node->GetItem(); ret = node->GetItem();
return DoJob::OK; return DoJob::OK;
} }
@@ -2733,7 +2737,7 @@ public:
{ {
current ++; current ++;
if( current == static_cast<int>(row)) if( current == static_cast<int>(row))
{ {
ret = wxDataViewItem( n ); ret = wxDataViewItem( n );
return DoJob::OK; return DoJob::OK;
} }
@@ -2776,7 +2780,7 @@ public:
{ {
current ++; current ++;
if( current == static_cast<int>(row)) if( current == static_cast<int>(row))
{ {
ret = node; ret = node;
return DoJob::OK; return DoJob::OK;
} }
@@ -2810,7 +2814,7 @@ public:
{ {
current ++; current ++;
if( current == static_cast<int>(row)) if( current == static_cast<int>(row))
{ {
ret = new wxDataViewTreeNode( parent ); ret = new wxDataViewTreeNode( parent );
ret->SetItem( wxDataViewItem( n )); ret->SetItem( wxDataViewItem( n ));
ret->SetHasChildren(false); ret->SetHasChildren(false);
@@ -2854,16 +2858,16 @@ wxDataViewEvent wxDataViewMainWindow::SendExpanderEvent( wxEventType type, const
bool wxDataViewMainWindow::IsExpanded( unsigned int row ) const bool wxDataViewMainWindow::IsExpanded( unsigned int row ) const
{ {
if (IsVirtualList()) if (IsVirtualList())
return false; return false;
wxDataViewTreeNode * node = GetTreeNodeByRow(row); wxDataViewTreeNode * node = GetTreeNodeByRow(row);
if (!node) if (!node)
return false; return false;
if (!node->HasChildren()) if (!node->HasChildren())
{ {
delete node; delete node;
return false; return false;
} }
return node->IsOpen(); return node->IsOpen();
@@ -2873,7 +2877,7 @@ bool wxDataViewMainWindow::IsExpanded( unsigned int row ) const
void wxDataViewMainWindow::OnExpanding( unsigned int row ) void wxDataViewMainWindow::OnExpanding( unsigned int row )
{ {
if (IsVirtualList()) if (IsVirtualList())
return; return;
wxDataViewTreeNode * node = GetTreeNodeByRow(row); wxDataViewTreeNode * node = GetTreeNodeByRow(row);
if( node != NULL ) if( node != NULL )
@@ -2882,39 +2886,39 @@ void wxDataViewMainWindow::OnExpanding( unsigned int row )
{ {
if( !node->IsOpen()) if( !node->IsOpen())
{ {
wxDataViewEvent e = SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING,node->GetItem()); wxDataViewEvent e = SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING,node->GetItem());
//Check if the user prevent expanding //Check if the user prevent expanding
if( e.GetSkipped() ) if( e.GetSkipped() )
return; return;
node->ToggleOpen(); node->ToggleOpen();
//Here I build the children of current node //Here I build the children of current node
if( node->GetChildrenNumber() == 0 ) if( node->GetChildrenNumber() == 0 )
{ {
SortPrepare(); SortPrepare();
::BuildTreeHelper(GetOwner()->GetModel(), node->GetItem(), node); ::BuildTreeHelper(GetOwner()->GetModel(), node->GetItem(), node);
} }
// By expanding the node all row indices that are currently in the selection list // By expanding the node all row indices that are currently in the selection list
// and are greater than our node have become invalid. So we have to correct that now. // and are greater than our node have become invalid. So we have to correct that now.
const unsigned rowAdjustment = node->GetSubTreeCount(); const unsigned rowAdjustment = node->GetSubTreeCount();
for(unsigned i=0; i<m_selection.size(); ++i) for(unsigned i=0; i<m_selection.size(); ++i)
{ {
const unsigned testRow = m_selection[i]; const unsigned testRow = m_selection[i];
// all rows above us are not affected, so skip them // all rows above us are not affected, so skip them
if(testRow <= row) if(testRow <= row)
continue; continue;
m_selection[i] += rowAdjustment; m_selection[i] += rowAdjustment;
} }
if(m_currentRow > row) if(m_currentRow > row)
ChangeCurrentRow(m_currentRow + rowAdjustment); ChangeCurrentRow(m_currentRow + rowAdjustment);
m_count = -1; m_count = -1;
UpdateDisplay(); UpdateDisplay();
//Send the expanded event //Send the expanded event
SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED,node->GetItem()); SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED,node->GetItem());
} }
else else
{ {
@@ -2932,7 +2936,7 @@ void wxDataViewMainWindow::OnExpanding( unsigned int row )
void wxDataViewMainWindow::OnCollapsing(unsigned int row) void wxDataViewMainWindow::OnCollapsing(unsigned int row)
{ {
if (IsVirtualList()) if (IsVirtualList())
return; return;
wxDataViewTreeNode * node = GetTreeNodeByRow(row); wxDataViewTreeNode * node = GetTreeNodeByRow(row);
if( node != NULL ) if( node != NULL )
@@ -2945,53 +2949,53 @@ void wxDataViewMainWindow::OnCollapsing(unsigned int row)
if( e.GetSkipped() ) if( e.GetSkipped() )
return; return;
// Find out if there are selected items below the current node. // Find out if there are selected items below the current node.
bool selectCollapsingRow = false; bool selectCollapsingRow = false;
const unsigned rowAdjustment = node->GetSubTreeCount(); const unsigned rowAdjustment = node->GetSubTreeCount();
unsigned maxRowToBeTested = row + rowAdjustment; unsigned maxRowToBeTested = row + rowAdjustment;
for(unsigned i=0; i<m_selection.size(); ++i) for(unsigned i=0; i<m_selection.size(); ++i)
{ {
const unsigned testRow = m_selection[i]; const unsigned testRow = m_selection[i];
if(testRow > row && testRow <= maxRowToBeTested) if(testRow > row && testRow <= maxRowToBeTested)
{ {
selectCollapsingRow = true; selectCollapsingRow = true;
// get out as soon as we have found a node that is selected // get out as soon as we have found a node that is selected
break; break;
} }
} }
node->ToggleOpen(); node->ToggleOpen();
// If the node to be closed has selected items the user won't see those any longer. // If the node to be closed has selected items the user won't see those any longer.
// We select the collapsing node in this case. // We select the collapsing node in this case.
if(selectCollapsingRow) if(selectCollapsingRow)
{ {
SelectAllRows(false); SelectAllRows(false);
ChangeCurrentRow(row); ChangeCurrentRow(row);
SelectRow(row, true); SelectRow(row, true);
SendSelectionChangedEvent(GetItemByRow(row)); SendSelectionChangedEvent(GetItemByRow(row));
} }
else else
{ {
// if there were no selected items below our node we still need to "fix" the // if there were no selected items below our node we still need to "fix" the
// selection list to adjust for the changing of the row indices. // selection list to adjust for the changing of the row indices.
// We actually do the opposite of what we are doing in OnExpanding(). // We actually do the opposite of what we are doing in OnExpanding().
for(unsigned i=0; i<m_selection.size(); ++i) for(unsigned i=0; i<m_selection.size(); ++i)
{ {
const unsigned testRow = m_selection[i]; const unsigned testRow = m_selection[i];
// all rows above us are not affected, so skip them // all rows above us are not affected, so skip them
if(testRow <= row) if(testRow <= row)
continue; continue;
m_selection[i] -= rowAdjustment; m_selection[i] -= rowAdjustment;
} }
// if the "current row" is being collapsed away we change it to the current row ;-) // if the "current row" is being collapsed away we change it to the current row ;-)
if(m_currentRow > row && m_currentRow <= maxRowToBeTested) if(m_currentRow > row && m_currentRow <= maxRowToBeTested)
ChangeCurrentRow(row); ChangeCurrentRow(row);
else if(m_currentRow > row) else if(m_currentRow > row)
ChangeCurrentRow(m_currentRow - rowAdjustment); ChangeCurrentRow(m_currentRow - rowAdjustment);
} }
m_count = -1; m_count = -1;
UpdateDisplay(); UpdateDisplay();
@@ -3059,7 +3063,7 @@ wxDataViewTreeNode * wxDataViewMainWindow::FindNode( const wxDataViewItem & item
if (nodes[i]->GetItem() == (**iter)) if (nodes[i]->GetItem() == (**iter))
{ {
if (nodes[i]->GetItem() == item) if (nodes[i]->GetItem() == item)
return nodes[i]; return nodes[i];
node = nodes[i]; node = nodes[i];
found = true; found = true;
@@ -3108,10 +3112,10 @@ wxRect wxDataViewMainWindow::GetItemRect( const wxDataViewItem & item, const wxD
wxDataViewColumn *col = NULL; wxDataViewColumn *col = NULL;
for( int i = 0, cols = GetOwner()->GetColumnCount(); i < cols; i ++ ) for( int i = 0, cols = GetOwner()->GetColumnCount(); i < cols; i ++ )
{ {
col = GetOwner()->GetColumnAt( i ); col = GetOwner()->GetColumnAt( i );
x += col->GetWidth(); x += col->GetWidth();
if( GetOwner()->GetColumnAt(i+1) == column ) if( GetOwner()->GetColumnAt(i+1) == column )
break; break;
} }
int w = col->GetWidth(); int w = col->GetWidth();
m_owner->CalcScrolledPosition( x, y, &x, &y ); m_owner->CalcScrolledPosition( x, y, &x, &y );
@@ -3140,7 +3144,7 @@ class ItemToRowJob : public DoJob
public: public:
ItemToRowJob(const wxDataViewItem& item_, ItemList::const_iterator iter) ItemToRowJob(const wxDataViewItem& item_, ItemList::const_iterator iter)
: m_iter(iter), : m_iter(iter),
item(item_) item(item_)
{ {
ret = -1; ret = -1;
} }
@@ -3148,22 +3152,22 @@ public:
//Maybe binary search will help to speed up this process //Maybe binary search will help to speed up this process
virtual int operator() ( wxDataViewTreeNode * node) virtual int operator() ( wxDataViewTreeNode * node)
{ {
ret ++; ret ++;
if( node->GetItem() == item ) if( node->GetItem() == item )
{ {
return DoJob::OK; return DoJob::OK;
} }
if( node->GetItem() == **m_iter ) if( node->GetItem() == **m_iter )
{ {
m_iter++; m_iter++;
return DoJob::CONT; return DoJob::CONT;
} }
else else
{ {
ret += node->GetSubTreeCount(); ret += node->GetSubTreeCount();
return DoJob::IGR; return DoJob::IGR;
} }
} }
@@ -3289,7 +3293,7 @@ void wxDataViewMainWindow::DestroyTree()
{ {
if (!IsVirtualList()) if (!IsVirtualList())
{ {
::DestroyTreeHelper(m_root); ::DestroyTreeHelper(m_root);
m_count = 0; m_count = 0;
m_root = NULL; m_root = NULL;
} }
@@ -3338,11 +3342,11 @@ void wxDataViewMainWindow::OnChar( wxKeyEvent &event )
break; break;
//Add the process for tree expanding/collapsing //Add the process for tree expanding/collapsing
case WXK_LEFT: case WXK_LEFT:
OnCollapsing(m_currentRow); OnCollapsing(m_currentRow);
break; break;
case WXK_RIGHT: case WXK_RIGHT:
OnExpanding( m_currentRow); OnExpanding( m_currentRow);
break; break;
case WXK_END: case WXK_END:
if (!IsEmpty()) if (!IsEmpty())
OnArrowChar( GetRowCount() - 1, event ); OnArrowChar( GetRowCount() - 1, event );
@@ -3432,11 +3436,11 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
int indent = node->GetIndentLevel(); int indent = node->GetIndentLevel();
indent = GetOwner()->GetIndent()*indent; indent = GetOwner()->GetIndent()*indent;
// we make the rectangle we are looking in a bit bigger than the actual // we make the rectangle we are looking in a bit bigger than the actual
// visual expander so the user can hit that little thing reliably // visual expander so the user can hit that little thing reliably
wxRect rect( xpos + indent, wxRect rect( xpos + indent,
GetLineStart( current ) + (GetLineHeight(current) - m_lineHeight)/2, GetLineStart( current ) + (GetLineHeight(current) - m_lineHeight)/2,
m_lineHeight, m_lineHeight); m_lineHeight, m_lineHeight);
if( rect.Contains(x, y) ) if( rect.Contains(x, y) )
{ {
//So the mouse is over the expander //So the mouse is over the expander
@@ -3530,17 +3534,17 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
wxDataViewItem item = GetItemByRow(current); wxDataViewItem item = GetItemByRow(current);
bool ignore_other_columns = bool ignore_other_columns =
((GetOwner()->GetExpanderColumn() != col) && ((GetOwner()->GetExpanderColumn() != col) &&
(model->IsContainer(item)) && (model->IsContainer(item)) &&
(!model->HasContainerColumns(item))); (!model->HasContainerColumns(item)));
if (event.LeftDClick()) if (event.LeftDClick())
{ {
if(hoverOverExpander) if(hoverOverExpander)
{ {
// a double click on the expander will be converted into a "simulated" normal click // a double click on the expander will be converted into a "simulated" normal click
simulateClick = true; simulateClick = true;
} }
else if ( current == m_lineLastClicked ) else if ( current == m_lineLastClicked )
{ {
if ((!ignore_other_columns) && (cell->GetMode() == wxDATAVIEW_CELL_ACTIVATABLE)) if ((!ignore_other_columns) && (cell->GetMode() == wxDATAVIEW_CELL_ACTIVATABLE))
{ {
@@ -3548,7 +3552,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
model->GetValue( value, item, col->GetModelColumn() ); model->GetValue( value, item, col->GetModelColumn() );
cell->SetValue( value ); cell->SetValue( value );
wxRect cell_rect( xpos, GetLineStart( current ), wxRect cell_rect( xpos, GetLineStart( current ),
col->GetWidth(), GetLineHeight( current ) ); col->GetWidth(), GetLineHeight( current ) );
cell->Activate( cell_rect, model, item, col->GetModelColumn() ); cell->Activate( cell_rect, model, item, col->GetModelColumn() );
} }
@@ -3633,17 +3637,17 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
{ {
} }
if((event.LeftDown() || simulateClick) && hoverOverExpander) if((event.LeftDown() || simulateClick) && hoverOverExpander)
{ {
wxDataViewTreeNode* node = GetTreeNodeByRow(current); wxDataViewTreeNode* node = GetTreeNodeByRow(current);
// hoverOverExpander being true tells us that our node must be valid and have children. // hoverOverExpander being true tells us that our node must be valid and have children.
// So we don't need any extra checks. // So we don't need any extra checks.
if( node->IsOpen() ) if( node->IsOpen() )
OnCollapsing(current); OnCollapsing(current);
else else
OnExpanding(current); OnExpanding(current);
} }
else if ((event.LeftDown() || simulateClick) && !hoverOverExpander) else if ((event.LeftDown() || simulateClick) && !hoverOverExpander)
{ {
SetFocus(); SetFocus();
@@ -3682,7 +3686,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
ChangeCurrentRow(current); ChangeCurrentRow(current);
unsigned int lineFrom = oldCurrentRow, unsigned int lineFrom = oldCurrentRow,
lineTo = current; lineTo = current;
if ( lineTo < lineFrom ) if ( lineTo < lineFrom )
{ {
@@ -3719,7 +3723,7 @@ void wxDataViewMainWindow::OnMouse( wxMouseEvent &event )
model->GetValue( value, item, col->GetModelColumn() ); model->GetValue( value, item, col->GetModelColumn() );
cell->SetValue( value ); cell->SetValue( value );
wxRect cell_rect( xpos, GetLineStart( current ), wxRect cell_rect( xpos, GetLineStart( current ),
col->GetWidth(), GetLineHeight( current ) ); col->GetWidth(), GetLineHeight( current ) );
/* ignore ret */ cell->LeftClick( event.GetPosition(), cell_rect, model, item, col->GetModelColumn()); /* ignore ret */ cell->LeftClick( event.GetPosition(), cell_rect, model, item, col->GetModelColumn());
} }
} }
@@ -3784,8 +3788,8 @@ void wxDataViewCtrl::Init()
} }
bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id, bool wxDataViewCtrl::Create(wxWindow *parent, wxWindowID id,
const wxPoint& pos, const wxSize& size, const wxPoint& pos, const wxSize& size,
long style, const wxValidator& validator ) long style, const wxValidator& validator )
{ {
// if ( (style & wxBORDER_MASK) == 0) // if ( (style & wxBORDER_MASK) == 0)
// style |= wxBORDER_SUNKEN; // style |= wxBORDER_SUNKEN;
@@ -3827,8 +3831,8 @@ wxBorder wxDataViewCtrl::GetDefaultBorder() const
#ifdef __WXMSW__ #ifdef __WXMSW__
WXLRESULT wxDataViewCtrl::MSWWindowProc(WXUINT nMsg, WXLRESULT wxDataViewCtrl::MSWWindowProc(WXUINT nMsg,
WXWPARAM wParam, WXWPARAM wParam,
WXLPARAM lParam) WXLPARAM lParam)
{ {
WXLRESULT rc = wxDataViewCtrlBase::MSWWindowProc(nMsg, wParam, lParam); WXLRESULT rc = wxDataViewCtrlBase::MSWWindowProc(nMsg, wParam, lParam);
@@ -3848,7 +3852,7 @@ wxSize wxDataViewCtrl::GetSizeAvailableForScrollTarget(const wxSize& size)
{ {
wxSize newsize = size; wxSize newsize = size;
if (!HasFlag(wxDV_NO_HEADER) && (m_headerArea)) if (!HasFlag(wxDV_NO_HEADER) && (m_headerArea))
newsize.y -= m_headerArea->GetSize().y; newsize.y -= m_headerArea->GetSize().y;
return newsize; return newsize;
} }
@@ -3976,7 +3980,7 @@ wxDataViewColumn *wxDataViewCtrl::GetColumnAt(unsigned int pos) const
// columns can't be reordered if there is no header window which allows // columns can't be reordered if there is no header window which allows
// to do this // to do this
const unsigned idx = m_headerArea ? m_headerArea->GetColumnsOrder()[pos] const unsigned idx = m_headerArea ? m_headerArea->GetColumnsOrder()[pos]
: pos; : pos;
return GetColumn(idx); return GetColumn(idx);
} }
@@ -3994,7 +3998,7 @@ int wxDataViewCtrl::GetColumnIndex(const wxDataViewColumn *column) const
} }
void wxDataViewCtrl::ColumnMoved(wxDataViewColumn * WXUNUSED(col), void wxDataViewCtrl::ColumnMoved(wxDataViewColumn * WXUNUSED(col),
unsigned int WXUNUSED(new_pos)) unsigned int WXUNUSED(new_pos))
{ {
// do _not_ reorder m_cols elements here, they should always be in the // do _not_ reorder m_cols elements here, they should always be in the
// order in which columns were added, we only display the columns in // order in which columns were added, we only display the columns in
@@ -4044,7 +4048,7 @@ int wxDataViewCtrl::GetColumnPosition( const wxDataViewColumn *column ) const
wxDataViewColumn *wxDataViewCtrl::GetSortingColumn() const wxDataViewColumn *wxDataViewCtrl::GetSortingColumn() const
{ {
return m_sortingColumnIdx == wxNOT_FOUND ? NULL return m_sortingColumnIdx == wxNOT_FOUND ? NULL
: GetColumn(m_sortingColumnIdx); : GetColumn(m_sortingColumnIdx);
} }
//Selection code with wxDataViewItem as parameters //Selection code with wxDataViewItem as parameters
@@ -4277,7 +4281,7 @@ bool wxDataViewCtrl::IsExpanded( const wxDataViewItem & item ) const
} }
#endif #endif
// !wxUSE_GENERICDATAVIEWCTRL // !wxUSE_GENERICDATAVIEWCTRL
#endif #endif

View File

@@ -2243,6 +2243,9 @@ wxTextCtrl *wxListMainWindow::EditLabel(long item, wxClassInfo* textControlClass
// been added and no screen update taken place. // been added and no screen update taken place.
if ( m_dirty ) if ( m_dirty )
{ {
// TODO: use wxTheApp->SafeYieldFor(NULL, wxEVT_CATEGORY_UI) instead
// so that no pending events may change the item count (see below)
// IMPORTANT: needs to be tested!
wxSafeYield(); wxSafeYield();
// Pending events dispatched by wxSafeYield might have changed the item // Pending events dispatched by wxSafeYield might have changed the item

View File

@@ -403,6 +403,9 @@ wxProgressDialog::Update(int value, const wxString& newmsg, bool *skip)
m_msg->SetLabel(_("Done.")); m_msg->SetLabel(_("Done."));
} }
// allow the window to repaint:
// NOTE: since we yield only for UI events with this call, there
// should be no side-effects
wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI); wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI);
(void)ShowModal(); (void)ShowModal();
@@ -453,6 +456,8 @@ bool wxProgressDialog::DoAfterUpdate(bool *skip)
{ {
// we have to yield because not only we want to update the display but // we have to yield because not only we want to update the display but
// also to process the clicks on the cancel and skip buttons // also to process the clicks on the cancel and skip buttons
// NOTE: using YieldFor() this call shouldn't give re-entrancy problems
// for event handlers not interested to UI/user-input events.
wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI|wxEVT_CATEGORY_USER_INPUT); wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI|wxEVT_CATEGORY_USER_INPUT);
Update(); Update();
@@ -672,6 +677,9 @@ void wxProgressDialog::UpdateMessage(const wxString &newmsg)
Fit(); // adapt to the new label size Fit(); // adapt to the new label size
// allow the window to repaint:
// NOTE: since we yield only for UI events with this call, there
// should be no side-effects
wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI); wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI);
} }
} }

View File

@@ -3576,6 +3576,8 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event )
#if defined(__WXMSW__) || defined(__WXMAC__) || defined(__WXGTK20__) #if defined(__WXMSW__) || defined(__WXMAC__) || defined(__WXGTK20__)
Update(); Update();
#else #else
// TODO: remove this call or use wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI)
// instead (needs to be tested!)
wxYieldIfNeeded(); wxYieldIfNeeded();
#endif #endif
} }
@@ -3606,9 +3608,11 @@ void wxGenericTreeCtrl::OnMouse( wxMouseEvent &event )
SetCursor(m_oldCursor); SetCursor(m_oldCursor);
#if defined( __WXMSW__ ) || defined(__WXMAC__) #if defined( __WXMSW__ ) || defined(__WXMAC__) || defined(__WXGTK20__)
Update(); Update();
#else #else
// TODO: remove this call or use wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI)
// instead (needs to be tested!)
wxYieldIfNeeded(); wxYieldIfNeeded();
#endif #endif
} }

View File

@@ -1247,10 +1247,11 @@ void wxTopLevelWindowGTK::RequestUserAttention(int flags)
bool new_hint_value = false; bool new_hint_value = false;
// FIXME: This is a workaround to focus handling problem // FIXME: This is a workaround to focus handling problem
// If RequestUserAttention is called for example right after a wxSleep, OnInternalIdle hasn't // If RequestUserAttention is called for example right after a wxSleep, OnInternalIdle
// yet been processed, and the internal focus system is not up to date yet. // hasn't yet been processed, and the internal focus system is not up to date yet.
// wxYieldIfNeeded ensures the processing of it, but can have unwanted side effects - MR // YieldFor(wxEVT_CATEGORY_UI) ensures the processing of it (hopefully it
::wxYieldIfNeeded(); // won't have side effects) - MR
wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI);
if(m_urgency_hint >= 0) if(m_urgency_hint >= 0)
g_source_remove(m_urgency_hint); g_source_remove(m_urgency_hint);