void wxWindowDFB::PaintWindow(const wxRect& rect) { wxCHECK_RET( !IsFrozen() && IsShown(), "shouldn't be called" ); wxLogTrace(TRACE_PAINT, "%p ('%s'): painting region [%i,%i,%i,%i]", this, GetName().c_str(), rect.x, rect.y, rect.GetRight(), rect.GetBottom()); m_updateRegion = rect; // FIXME_DFB: don't waste time rendering the area if it's fully covered // by some children, go directly to rendering the children // (unless some child has HasTransparentBackground()=true!) // NB: unconditionally send wxEraseEvent, because our implementation of // wxWindow::Refresh() ignores the eraseBack argument wxWindowDC dc((wxWindow*)this); wxEraseEvent eventEr(m_windowId, &dc); eventEr.SetEventObject(this); HandleWindowEvent(eventEr); wxRect clientRect(GetClientRect()); // only send wxNcPaintEvent if drawing at least part of nonclient area: if ( !clientRect.Contains(rect) ) { wxNcPaintEvent eventNc(GetId()); eventNc.SetEventObject(this); HandleWindowEvent(eventNc); } else { wxLogTrace(TRACE_PAINT, "%p ('%s'): not sending wxNcPaintEvent", this, GetName().c_str()); } // only send wxPaintEvent if drawing at least part of client area: if ( rect.Intersects(clientRect) ) { wxPaintEvent eventPt(GetId()); eventPt.SetEventObject(this); HandleWindowEvent(eventPt); } else { wxLogTrace(TRACE_PAINT, "%p ('%s'): not sending wxPaintEvent", this, GetName().c_str()); } // draw window's overlays on top of the painted window, if we have any: PaintOverlays(rect); m_updateRegion.Clear(); // client area portion of 'rect': wxRect rectClientOnly(rect); rectClientOnly.Intersect(clientRect); // paint the children: wxPoint origin = GetClientAreaOrigin(); wxWindowList& children = GetChildren(); for ( wxWindowList::iterator i = children.begin(); i != children.end(); ++i ) { wxWindow *child = *i; if ( child->IsFrozen() || !child->IsShown() ) continue; // don't paint anything if the window is frozen or hidden // compute child's area to repaint wxRect childrect(child->GetRect()); childrect.Offset(origin); if ( child->CanBeOutsideClientArea() ) childrect.Intersect(rect); else childrect.Intersect(rectClientOnly); if ( childrect.IsEmpty() ) continue; // and repaint it: childrect.Offset(-child->GetPosition()); childrect.Offset(-origin); child->PaintWindow(childrect); } }
void wxWindow::Refresh(bool eraseBackground, const wxRect *rect) { wxRect rectClient; // the same rectangle in client coordinates wxPoint origin = GetClientAreaOrigin(); wxSize size = GetClientSize(); if ( rect ) { // the rectangle passed as argument is in client coordinates rectClient = *rect; // don't refresh anything beyond the client area (scrollbars for // example) if ( rectClient.GetRight() > size.x ) rectClient.SetRight(size.x); if ( rectClient.GetBottom() > size.y ) rectClient.SetBottom(size.y); } else // refresh the entire client area { // x,y is already set to 0 by default rectClient.SetSize(size); } // convert refresh rectangle to window coordinates: wxRect rectWin(rectClient); rectWin.Offset(origin); // debugging helper #ifdef WXDEBUG_REFRESH static bool s_refreshDebug = false; if ( s_refreshDebug ) { wxWindowDC dc(this); dc.SetBrush(*wxCYAN_BRUSH); dc.SetPen(*wxTRANSPARENT_PEN); dc.DrawRectangle(rectWin); // under Unix we use "--sync" X option for this #if defined(__WXMSW__) && !defined(__WXMICROWIN__) ::GdiFlush(); ::Sleep(200); #endif // __WXMSW__ } #endif // WXDEBUG_REFRESH wxWindowNative::Refresh(eraseBackground, &rectWin); // Refresh all sub controls if any. wxWindowList& children = GetChildren(); for ( wxWindowList::iterator i = children.begin(); i != children.end(); ++i ) { wxWindow *child = *i; // only refresh subcontrols if they are visible: if ( child->IsTopLevel() || !child->IsShown() || child->IsFrozen() ) continue; // ...and when the subcontrols are in the update region: wxRect childrect(child->GetRect()); childrect.Intersect(rectClient); if ( childrect.IsEmpty() ) continue; // refresh the subcontrol now: childrect.Offset(-child->GetPosition()); // NB: We must call wxWindowNative version because we need to refresh // the entire control, not just its client area, and this is why we // don't account for child client area origin here neither. Also // note that we don't pass eraseBackground to the child, but use // true instead: this is because we can't be sure that // eraseBackground=false is safe for children as well and not only // for the parent. child->wxWindowNative::Refresh(eraseBackground, &childrect); } }