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. + 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. - 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. + 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,43 @@ 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: - case wxRIGHT: - // Draw the bitmap normally, its rightmost or bottom part could be - // truncated, as it's meant to be. - dc.DrawBitmap(m_bitmap, 0, 0); + // The bitmap will be extended to the right. + p.x = size.x; + p.y = 0; 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()); + // The bitmap will be extended from the top. + p.x = 0; + p.y = 0; + break; + + case wxRIGHT: + // 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 @@ -227,6 +248,67 @@ void wxBannerWindow::DrawBitmapBackground(wxDC& dc) 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. + 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 + // some enum elements in the switch, it can't really happen. + case wxALL: + wxFAIL_MSG( wxS("Unreachable") ); + } + + if ( rectSolid.width > 0 && rectSolid.height > 0 ) + { + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(GetBitmapBg()); + dc.DrawRectangle(rectSolid); + } } void