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(); void CorrectEditorWidgetPosY();
#if WXWIN_COMPATIBILITY_3_0
wxDEPRECATED_MSG("use two-argument function DoDrawItems(dc,rect)")
int DoDrawItems( wxDC& dc, 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, const wxRect* itemsRect,
bool isBuffered ) const; bool isBuffered ) const;
#else
int DoDrawItems( wxDC& dc,
const wxRect* itemsRect ) const;
#endif
/** Draws an expand/collapse (ie. +/-) button. /** Draws an expand/collapse (ie. +/-) button.
*/ */

View File

@@ -1838,8 +1838,25 @@ wxPGProperty* wxPropertyGrid::DoGetItemAtY( int y ) const
void wxPropertyGrid::OnPaint( wxPaintEvent& WXUNUSED(event) ) void wxPropertyGrid::OnPaint( wxPaintEvent& WXUNUSED(event) )
{ {
wxPaintDC dc(this); wxDC* dcPtr = NULL;
PrepareDC(dc); 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 // Don't paint after destruction has begun
if ( !HasInternalFlag(wxPG_FL_INITIALIZED) ) if ( !HasInternalFlag(wxPG_FL_INITIALIZED) )
@@ -1864,7 +1881,10 @@ void wxPropertyGrid::OnPaint( wxPaintEvent& WXUNUSED(event) )
r.height = GetClientSize().y; r.height = GetClientSize().y;
// Repaint this rectangle // 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 // We assume that the size set when grid is shown
// is what is desired. // is what is desired.
@@ -1976,73 +1996,32 @@ void wxPropertyGrid::DrawItems( wxDC& dc,
vx *= wxPG_PIXELS_PER_UNIT; vx *= wxPG_PIXELS_PER_UNIT;
vy *= 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 // items added check
if ( m_pState->m_itemsAdded ) PrepareAfterItemsAdded(); if ( m_pState->m_itemsAdded ) PrepareAfterItemsAdded();
int paintFinishY = 0;
if ( m_pState->m_properties->GetChildCount() > 0 ) if ( m_pState->m_properties->GetChildCount() > 0 )
{ {
wxDC* dcPtr = &dc; // paintFinishY and drawBottomY are in buffer/physical space
bool isBuffered = false; int paintFinishY = DoDrawItems(dc, itemsRect);
int drawBottomY = itemsRect->y + itemsRect->height - vy;
wxMemoryDC* bufferDC = NULL; // Clear area beyond last painted property
if ( paintFinishY < drawBottomY )
if ( !(GetExtraStyle() & wxPG_EX_NATIVE_DOUBLE_BUFFERING) )
{ {
if ( !m_doubleBuffer ) dc.SetPen(m_colEmptySpace);
{ dc.SetBrush(m_colEmptySpace);
paintFinishY = itemsRect->y; dc.DrawRectangle(0, paintFinishY,
dcPtr = NULL; m_width,
} drawBottomY );
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;
} }
} }
else else
{ {
// itemRect is in virtual grid space
wxRect drawRect(itemsRect->x - vx,
itemsRect->y - vy,
itemsRect->width,
itemsRect->height);
// Just clear the area // Just clear the area
dc.SetPen(m_colEmptySpace); dc.SetPen(m_colEmptySpace);
dc.SetBrush(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, const wxRect* itemsRect,
bool isBuffered ) const bool isBuffered ) const
#else
int wxPropertyGrid::DoDrawItems( wxDC& dc,
const wxRect* itemsRect ) const
#endif
{ {
const wxPGProperty* firstItem; const wxPGProperty* firstItem;
const wxPGProperty* lastItem; const wxPGProperty* lastItem;
@@ -2095,45 +2079,37 @@ int wxPropertyGrid::DoDrawItems( wxDC& dc,
"invalid y values" ); "invalid y values" );
/* /*
wxLogDebug(" -> DoDrawItems ( \"%s\" -> \"%s\" wxLogDebug(" -> DoDrawItems(\"%s\" -> \"%s\""
"height=%i (ch=%i), itemsRect = 0x%lX )", " %i -> %i height=%i (ch=%i), itemsRect = 0x%lX %i,%i %ix%i)",
firstItem->GetLabel().c_str(), firstItem->GetLabel().c_str(),
lastItem->GetLabel().c_str(), lastItem->GetLabel().c_str(),
firstItemTopY, lastItemBottomY,
(int)(lastItemBottomY - firstItemTopY), (int)(lastItemBottomY - firstItemTopY),
(int)m_height, (int)m_height,
(unsigned long)&itemsRect ); (unsigned long)&itemsRect,
itemsRect->x, itemsRect->y, itemsRect->width, itemsRect->height );
*/ */
wxRect r;
long windowStyle = m_windowStyle; long windowStyle = m_windowStyle;
#if WXWIN_COMPATIBILITY_3_0
int xRelMod = 0; int xRelMod = 0;
// // Buffer's y = 0, so align itemsRect and coordinates to that
// 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;
if ( isBuffered ) if ( isBuffered )
{ {
xRelMod = itemsRect->x; xRelMod = itemsRect->x;
yRelMod = itemsRect->y;
//
// itemsRect conversion // itemsRect conversion
cr2 = *itemsRect; firstItemTopY -= itemsRect->y;
cr2.x -= xRelMod; lastItemBottomY -= itemsRect->y;
cr2.y -= yRelMod;
itemsRect = &cr2;
firstItemTopY -= yRelMod;
lastItemBottomY -= yRelMod;
} }
#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; int x = m_marginWidth - xRelMod;