From 4e2b91bb27c3ab9667b1a8255e423777150b2daa Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 28 Nov 2011 18:58:52 +0000 Subject: [PATCH] Extend wxBannerWindow background bitmap if necessary. Ensure that the entire banner window uses the same background colour as the bitmap, even when the bitmap is too small for the window size. This allows to avoid using huge bitmaps if extending the bitmap with solid colour looks good enough. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@69859 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/bannerwindow.h | 8 ++++ interface/wx/bannerwindow.h | 22 +++++---- src/generic/bannerwindow.cpp | 92 ++++++++++++++++++++++++++++++++++-- 3 files changed, 109 insertions(+), 13 deletions(-) diff --git a/include/wx/bannerwindow.h b/include/wx/bannerwindow.h index f5a9fde9c7..80c8eb9bc9 100644 --- a/include/wx/bannerwindow.h +++ b/include/wx/bannerwindow.h @@ -112,6 +112,10 @@ private: // configurable in the future. wxFont GetTitleFont() const; + // Return the colour to use for extending the bitmap. Non-const as it + // updates m_colBitmapBg if needed. + wxColour GetBitmapBg(); + // The window side along which the banner is laid out. wxDirection m_direction; @@ -119,6 +123,10 @@ private: // If valid, this bitmap is drawn as is. wxBitmap m_bitmap; + // If bitmap is valid, this is the colour we use to extend it if the bitmap + // is smaller than this window. It is computed on demand by GetBitmapBg(). + wxColour m_colBitmapBg; + // The title and main message to draw, used if m_bitmap is invalid. wxString m_title, m_message; diff --git a/interface/wx/bannerwindow.h b/interface/wx/bannerwindow.h index e91073ff3a..4cf80741c5 100644 --- a/interface/wx/bannerwindow.h +++ b/interface/wx/bannerwindow.h @@ -113,14 +113,20 @@ public: /** Provide the bitmap to use as background. - Notice that the bitmap should be big enough to always cover the entire - banner, e.g. for a horizontal banner with wxTOP style its width should - be bigger than any reasonable window size. - - For wxLEFT orientation the bitmap is truncated from the top, for wxTOP - and wxBOTTOM -- from the right and for wxRIGHT -- from the bottom, so - put the most important part of the bitmap information in the opposite - direction. + Notice that ideally the bitmap should be big enough to always cover the + entire banner, e.g. for a horizontal banner with wxTOP style its width + should be bigger than any reasonable window size. Otherwise the bitmap + is extended to cover the entire window area with a solid colour taken + from the bitmap pixel on the edge in which direction the extension + occurs so all bitmap pixels on this edge (top for wxLEFT, right for + wxTOP and wxBOTTOM and bottom for wxRIGHT) should have the same colour + to avoid jarring discontinuity. + + If, on the other hand, the bitmap is bigger than the window size, then + it is truncated. For wxLEFT orientation the bitmap is truncated from + the top, for wxTOP and wxBOTTOM -- from the right and for wxRIGHT -- + from the bottom, so put the most important part of the bitmap + information in the opposite direction where it will never be truncated. If no valid background bitmap is specified, the banner draws gradient background but if a valid bitmap is given here, the gradient is not diff --git a/src/generic/bannerwindow.cpp b/src/generic/bannerwindow.cpp index 4717d0440e..2585ec32a1 100644 --- a/src/generic/bannerwindow.cpp +++ b/src/generic/bannerwindow.cpp @@ -79,6 +79,8 @@ void wxBannerWindow::SetBitmap(const wxBitmap& bmp) { m_bitmap = bmp; + m_colBitmapBg = wxColour(); + InvalidateBestSize(); Refresh(); @@ -202,24 +204,97 @@ void wxBannerWindow::OnPaint(wxPaintEvent& WXUNUSED(event)) } } -void wxBannerWindow::DrawBitmapBackground(wxDC& dc) +wxColour wxBannerWindow::GetBitmapBg() { + if ( m_colBitmapBg.IsOk() ) + return m_colBitmapBg; + + // Determine the colour to use to extend the bitmap. It's the colour of the + // bitmap pixels at the edge closest to the area where it can be extended. + wxImage image(m_bitmap.ConvertToImage()); + + // The point we get the colour from. The choice is arbitrary and in general + // the bitmap should have the same colour on the entire edge of this point + // for extending it to look good. + wxPoint p; + + wxSize size = image.GetSize(); + size.x--; + size.y--; + switch ( m_direction ) { case wxTOP: case wxBOTTOM: + // The bitmap will be extended to the right. + p.x = size.x; + p.y = 0; + break; + + case wxLEFT: + // The bitmap will be extended from the top. + p.x = 0; + p.y = 0; + break; + case wxRIGHT: - // Draw the bitmap normally, its rightmost or bottom part could be - // truncated, as it's meant to be. + // The bitmap will be extended to the bottom. + p.x = 0; + p.y = size.y; + break; + + // This case is there only to prevent g++ warnings about not handling + // some enum elements in the switch, it can't really happen. + case wxALL: + wxFAIL_MSG( wxS("Unreachable") ); + } + + m_colBitmapBg.Set(image.GetRed(p.x, p.y), + image.GetGreen(p.x, p.y), + image.GetBlue(p.x, p.y)); + + return m_colBitmapBg; +} + +void wxBannerWindow::DrawBitmapBackground(wxDC& dc) +{ + // We may need to fill the part of the background not covered by the bitmap + // with the solid colour extending the bitmap, this rectangle will hold the + // area to be filled (which could be empty if the bitmap is big enough). + wxRect rectSolid; + + const wxSize size = GetClientSize(); + + switch ( m_direction ) + { + case wxTOP: + case wxBOTTOM: + // Draw the bitmap at the origin, its rightmost could be truncated, + // as it's meant to be. dc.DrawBitmap(m_bitmap, 0, 0); + + rectSolid.x = m_bitmap.GetWidth(); + rectSolid.width = size.x - rectSolid.x; + rectSolid.height = size.y; break; case wxLEFT: // The top most part of the bitmap may be truncated but its bottom // must be always visible so intentionally draw it possibly partly // outside of the window. - dc.DrawBitmap(m_bitmap, - 0, GetClientSize().y - m_bitmap.GetHeight()); + rectSolid.width = size.x; + rectSolid.height = size.y - m_bitmap.GetHeight(); + dc.DrawBitmap(m_bitmap, 0, rectSolid.height); + break; + + case wxRIGHT: + // Draw the bitmap at the origin, possibly truncating its + // bottommost part. + dc.DrawBitmap(m_bitmap, 0, 0); + + rectSolid.y = m_bitmap.GetHeight(); + rectSolid.height = size.y - rectSolid.y; + rectSolid.width = size.x; break; // This case is there only to prevent g++ warnings about not handling @@ -227,6 +302,13 @@ void wxBannerWindow::DrawBitmapBackground(wxDC& dc) case wxALL: wxFAIL_MSG( wxS("Unreachable") ); } + + if ( rectSolid.width > 0 && rectSolid.height > 0 ) + { + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(GetBitmapBg()); + dc.DrawRectangle(rectSolid); + } } void -- 2.45.2