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:
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user