Use wxBufferedPaintDC to implement double buffering in wxPG.

This also fixes drawing the PG when buffer is not available and there is necessary do draw directly on window DC.
wxPropertyGrid::DrawItems method is simplified and wxPropertyGrid::DoDrawItems method is reimplemented since its 3-rd argument (isBuffered) is unneeded anymore.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@78266 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Artur Wieczorek 2014-12-12 22:36:28 +00:00
parent d9d6247f37
commit 6ba0f3016b
2 changed files with 79 additions and 84 deletions

View File

@ -2138,9 +2138,28 @@ protected:
*/
void CorrectEditorWidgetPosY();
#if WXWIN_COMPATIBILITY_3_0
wxDEPRECATED_MSG("use two-argument function DoDrawItems(dc,rect)")
int DoDrawItems( wxDC& dc,
const wxRect* itemsRect,
bool isBuffered ) const
{
return DoDrawItemsBase(dc, itemsRect, isBuffered);
}
int DoDrawItems( wxDC& dc,
const wxRect* itemsRect ) const
{
return DoDrawItemsBase(dc, itemsRect, true);
}
int DoDrawItemsBase( wxDC& dc,
const wxRect* itemsRect,
bool isBuffered ) const;
#else
int DoDrawItems( wxDC& dc,
const wxRect* itemsRect ) const;
#endif
/** Draws an expand/collapse (ie. +/-) button.
*/

View File

@ -1838,8 +1838,25 @@ wxPGProperty* wxPropertyGrid::DoGetItemAtY( int y ) const
void wxPropertyGrid::OnPaint( wxPaintEvent& WXUNUSED(event) )
{
wxPaintDC dc(this);
PrepareDC(dc);
wxDC* dcPtr = NULL;
if ( !(GetExtraStyle() & wxPG_EX_NATIVE_DOUBLE_BUFFERING) )
{
if ( m_doubleBuffer )
{
dcPtr = new wxBufferedPaintDC(this, *m_doubleBuffer);
}
}
if ( !dcPtr )
{
dcPtr = new wxPaintDC(this);
}
wxASSERT( dcPtr );
PrepareDC(*dcPtr);
// Unused area will be cleared when drawing then items
/*
dcPtr->SetBackground(m_colEmptySpace);
dcPtr->Clear();
*/
// Don't paint after destruction has begun
if ( !HasInternalFlag(wxPG_FL_INITIALIZED) )
@ -1864,7 +1881,10 @@ void wxPropertyGrid::OnPaint( wxPaintEvent& WXUNUSED(event) )
r.height = GetClientSize().y;
// Repaint this rectangle
DrawItems( dc, r.y, r.y + r.height, &r );
DrawItems(*dcPtr, r.y, r.y + r.height, &r);
// This blits the buffer (if used) to the window DC.
delete dcPtr;
// We assume that the size set when grid is shown
// is what is desired.
@ -1976,73 +1996,32 @@ void wxPropertyGrid::DrawItems( wxDC& dc,
vx *= wxPG_PIXELS_PER_UNIT;
vy *= wxPG_PIXELS_PER_UNIT;
// itemRect is in virtual grid space
wxRect drawRect(itemsRect->x - vx,
itemsRect->y - vy,
itemsRect->width,
itemsRect->height);
// items added check
if ( m_pState->m_itemsAdded ) PrepareAfterItemsAdded();
int paintFinishY = 0;
if ( m_pState->m_properties->GetChildCount() > 0 )
{
wxDC* dcPtr = &dc;
bool isBuffered = false;
// paintFinishY and drawBottomY are in buffer/physical space
int paintFinishY = DoDrawItems(dc, itemsRect);
int drawBottomY = itemsRect->y + itemsRect->height - vy;
wxMemoryDC* bufferDC = NULL;
if ( !(GetExtraStyle() & wxPG_EX_NATIVE_DOUBLE_BUFFERING) )
// Clear area beyond last painted property
if ( paintFinishY < drawBottomY )
{
if ( !m_doubleBuffer )
{
paintFinishY = itemsRect->y;
dcPtr = NULL;
}
else
{
bufferDC = new wxMemoryDC();
// Use the same layout direction as the window DC uses
// to ensure that the text is rendered correctly.
bufferDC->SetLayoutDirection(dc.GetLayoutDirection());
// If nothing was changed, then just copy from double-buffer
bufferDC->SelectObject( *m_doubleBuffer );
dcPtr = bufferDC;
isBuffered = true;
}
}
if ( dcPtr )
{
// paintFinishY and drawBottomY are in buffer/physical space
paintFinishY = DoDrawItems( *dcPtr, itemsRect, isBuffered );
int drawBottomY = itemsRect->y + itemsRect->height - vy;
// Clear area beyond last painted property
if ( paintFinishY < drawBottomY )
{
dcPtr->SetPen(m_colEmptySpace);
dcPtr->SetBrush(m_colEmptySpace);
dcPtr->DrawRectangle(0, paintFinishY,
m_width,
drawBottomY );
}
}
if ( bufferDC )
{
dc.Blit( drawRect.x, drawRect.y, drawRect.width,
drawRect.height,
bufferDC, 0, 0, wxCOPY );
delete bufferDC;
dc.SetPen(m_colEmptySpace);
dc.SetBrush(m_colEmptySpace);
dc.DrawRectangle(0, paintFinishY,
m_width,
drawBottomY );
}
}
else
{
// itemRect is in virtual grid space
wxRect drawRect(itemsRect->x - vx,
itemsRect->y - vy,
itemsRect->width,
itemsRect->height);
// Just clear the area
dc.SetPen(m_colEmptySpace);
dc.SetBrush(m_colEmptySpace);
@ -2052,9 +2031,14 @@ void wxPropertyGrid::DrawItems( wxDC& dc,
// -----------------------------------------------------------------------
int wxPropertyGrid::DoDrawItems( wxDC& dc,
#if WXWIN_COMPATIBILITY_3_0
int wxPropertyGrid::DoDrawItemsBase( wxDC& dc,
const wxRect* itemsRect,
bool isBuffered ) const
#else
int wxPropertyGrid::DoDrawItems( wxDC& dc,
const wxRect* itemsRect ) const
#endif
{
const wxPGProperty* firstItem;
const wxPGProperty* lastItem;
@ -2095,45 +2079,37 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
"invalid y values" );
/*
wxLogDebug(" -> DoDrawItems ( \"%s\" -> \"%s\"
"height=%i (ch=%i), itemsRect = 0x%lX )",
wxLogDebug(" -> DoDrawItems(\"%s\" -> \"%s\""
" %i -> %i height=%i (ch=%i), itemsRect = 0x%lX %i,%i %ix%i)",
firstItem->GetLabel().c_str(),
lastItem->GetLabel().c_str(),
firstItemTopY, lastItemBottomY,
(int)(lastItemBottomY - firstItemTopY),
(int)m_height,
(unsigned long)&itemsRect );
(unsigned long)&itemsRect,
itemsRect->x, itemsRect->y, itemsRect->width, itemsRect->height );
*/
wxRect r;
long windowStyle = m_windowStyle;
#if WXWIN_COMPATIBILITY_3_0
int xRelMod = 0;
//
// For now, do some manual calculation for double buffering
// - buffer's y = 0, so align itemsRect and coordinates to that
//
// TODO: In future use wxAutoBufferedPaintDC (for example)
//
int yRelMod = 0;
wxRect cr2;
// Buffer's y = 0, so align itemsRect and coordinates to that
if ( isBuffered )
{
xRelMod = itemsRect->x;
yRelMod = itemsRect->y;
//
// itemsRect conversion
cr2 = *itemsRect;
cr2.x -= xRelMod;
cr2.y -= yRelMod;
itemsRect = &cr2;
firstItemTopY -= yRelMod;
lastItemBottomY -= yRelMod;
firstItemTopY -= itemsRect->y;
lastItemBottomY -= itemsRect->y;
}
#else
// Buffer's y = 0, so align itemsRect and coordinates to that
int xRelMod = itemsRect->x;
// itemsRect conversion
firstItemTopY -= itemsRect->y;
lastItemBottomY -= itemsRect->y;
#endif
int x = m_marginWidth - xRelMod;