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
This commit is contained in:
Vadim Zeitlin 2011-11-28 18:58:52 +00:00
parent e78e77e5ca
commit 4e2b91bb27
3 changed files with 113 additions and 17 deletions

View File

@ -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;

View File

@ -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

View File

@ -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