]>
Commit | Line | Data |
---|---|---|
ea11bf3a VZ |
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 | ||
94ed214d | 38 | const char wxBannerWindowNameStr[] = "bannerwindow"; |
ea11bf3a VZ |
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 |