Fix wxBannerWindowNameStr definition in DLL builds.
[wxWidgets.git] / src / generic / bannerwindow.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: wx/bannerwindow.h
3 // Purpose: wxBannerWindow class implementation
4 // Author: Vadim Zeitlin
5 // Created: 2011-08-16
6 // RCS-ID: $Id$
7 // Copyright: (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 #include "wx/wxprec.h"
12
13 #ifdef __BORLANDC__
14 #pragma hdrstop
15 #endif
16
17 #if wxUSE_BANNERWINDOW
18
19 #include "wx/bannerwindow.h"
20
21 #ifndef WX_PRECOMP
22 #include "wx/bitmap.h"
23 #include "wx/colour.h"
24 #endif
25
26 #include "wx/dcbuffer.h"
27
28 namespace
29 {
30
31 // Some constants for banner layout, currently they're hard coded but we could
32 // easily make them configurable if needed later.
33 const int MARGIN_X = 5;
34 const int MARGIN_Y = 5;
35
36 } // anonymous namespace
37
38 const char wxBannerWindowNameStr[] = "bannerwindow";
39
40 BEGIN_EVENT_TABLE(wxBannerWindow, wxWindow)
41 EVT_SIZE(wxBannerWindow::OnSize)
42 EVT_PAINT(wxBannerWindow::OnPaint)
43 END_EVENT_TABLE()
44
45 void wxBannerWindow::Init()
46 {
47 m_direction = wxLEFT;
48
49 m_colStart = *wxWHITE;
50 m_colEnd = *wxBLUE;
51 }
52
53 bool
54 wxBannerWindow::Create(wxWindow* parent,
55 wxWindowID winid,
56 wxDirection dir,
57 const wxPoint& pos,
58 const wxSize& size,
59 long style,
60 const wxString& name)
61 {
62 if ( !wxWindow::Create(parent, winid, pos, size, style, name) )
63 return false;
64
65 wxASSERT_MSG
66 (
67 dir == wxLEFT || dir == wxRIGHT || dir == wxTOP || dir == wxBOTTOM,
68 wxS("Invalid banner direction")
69 );
70
71 m_direction = dir;
72
73 SetBackgroundStyle(wxBG_STYLE_PAINT);
74
75 return true;
76 }
77
78 void wxBannerWindow::SetBitmap(const wxBitmap& bmp)
79 {
80 m_bitmap = bmp;
81
82 InvalidateBestSize();
83
84 Refresh();
85 }
86
87 void wxBannerWindow::SetText(const wxString& title, const wxString& message)
88 {
89 m_title = title;
90 m_message = message;
91
92 InvalidateBestSize();
93
94 Refresh();
95 }
96
97 void wxBannerWindow::SetGradient(const wxColour& start, const wxColour& end)
98 {
99 m_colStart = start;
100 m_colEnd = end;
101
102 Refresh();
103 }
104
105 wxFont wxBannerWindow::GetTitleFont() const
106 {
107 wxFont font = GetFont();
108 font.MakeBold().MakeLarger();
109 return font;
110 }
111
112 wxSize wxBannerWindow::DoGetBestClientSize() const
113 {
114 if ( m_bitmap.IsOk() )
115 {
116 return m_bitmap.GetSize();
117 }
118 else
119 {
120 wxClientDC dc(const_cast<wxBannerWindow *>(this));
121 const wxSize sizeText = dc.GetMultiLineTextExtent(m_message);
122
123 dc.SetFont(GetTitleFont());
124
125 const wxSize sizeTitle = dc.GetTextExtent(m_title);
126
127 wxSize sizeWin(wxMax(sizeTitle.x, sizeText.x), sizeTitle.y + sizeText.y);
128
129 // If we draw the text vertically width and height are swapped.
130 if ( m_direction == wxLEFT || m_direction == wxRIGHT )
131 wxSwap(sizeWin.x, sizeWin.y);
132
133 sizeWin += 2*wxSize(MARGIN_X, MARGIN_Y);
134
135 return sizeWin;
136 }
137 }
138
139 void wxBannerWindow::OnSize(wxSizeEvent& event)
140 {
141 Refresh();
142
143 event.Skip();
144 }
145
146 void wxBannerWindow::OnPaint(wxPaintEvent& WXUNUSED(event))
147 {
148 if ( m_bitmap.IsOk() && m_title.empty() && m_message.empty() )
149 {
150 // No need for buffering in this case.
151 wxPaintDC dc(this);
152
153 DrawBitmapBackground(dc);
154 }
155 else // We need to compose our contents ourselves.
156 {
157 wxAutoBufferedPaintDC dc(this);
158
159 // Deal with the background first.
160 if ( m_bitmap.IsOk() )
161 {
162 DrawBitmapBackground(dc);
163 }
164 else // Draw gradient background.
165 {
166 wxDirection gradientDir;
167 if ( m_direction == wxLEFT )
168 {
169 gradientDir = wxTOP;
170 }
171 else if ( m_direction == wxRIGHT )
172 {
173 gradientDir = wxBOTTOM;
174 }
175 else // For both wxTOP and wxBOTTOM.
176 {
177 gradientDir = wxRIGHT;
178 }
179
180 dc.GradientFillLinear(GetClientRect(), m_colStart, m_colEnd,
181 gradientDir);
182 }
183
184 // Now draw the text on top of it.
185 dc.SetFont(GetTitleFont());
186
187 wxPoint pos(MARGIN_X, MARGIN_Y);
188 DrawBannerTextLine(dc, m_title, pos);
189 pos.y += dc.GetTextExtent(m_title).y;
190
191 dc.SetFont(GetFont());
192
193 wxArrayString lines = wxSplit(m_message, '\n', '\0');
194 const unsigned numLines = lines.size();
195 for ( unsigned n = 0; n < numLines; n++ )
196 {
197 const wxString& line = lines[n];
198
199 DrawBannerTextLine(dc, line, pos);
200 pos.y += dc.GetTextExtent(line).y;
201 }
202 }
203 }
204
205 void wxBannerWindow::DrawBitmapBackground(wxDC& dc)
206 {
207 switch ( m_direction )
208 {
209 case wxTOP:
210 case wxBOTTOM:
211 case wxRIGHT:
212 // Draw the bitmap normally, its rightmost or bottom part could be
213 // truncated, as it's meant to be.
214 dc.DrawBitmap(m_bitmap, 0, 0);
215 break;
216
217 case wxLEFT:
218 // The top most part of the bitmap may be truncated but its bottom
219 // must be always visible so intentionally draw it possibly partly
220 // outside of the window.
221 dc.DrawBitmap(m_bitmap,
222 0, GetClientSize().y - m_bitmap.GetHeight());
223 break;
224
225 // This case is there only to prevent g++ warnings about not handling
226 // some enum elements in the switch, it can't really happen.
227 case wxALL:
228 wxFAIL_MSG( wxS("Unreachable") );
229 }
230 }
231
232 void
233 wxBannerWindow::DrawBannerTextLine(wxDC& dc,
234 const wxString& str,
235 const wxPoint& pos)
236 {
237 switch ( m_direction )
238 {
239 case wxTOP:
240 case wxBOTTOM:
241 // The simple case: we just draw the text normally.
242 dc.DrawText(str, pos);
243 break;
244
245 case wxLEFT:
246 // We draw the text vertically and start from the lower left
247 // corner and not the upper left one as usual.
248 dc.DrawRotatedText(str, pos.y, GetClientSize().y - pos.x, 90);
249 break;
250
251 case wxRIGHT:
252 // We also draw the text vertically but now we start from the upper
253 // right corner and draw it from top to bottom.
254 dc.DrawRotatedText(str, GetClientSize().x - pos.y, pos.x, -90);
255 break;
256
257 case wxALL:
258 wxFAIL_MSG( wxS("Unreachable") );
259 }
260 }
261
262 #endif // wxUSE_BANNERWINDOW