]> git.saurik.com Git - wxWidgets.git/blame - src/generic/bannerwindow.cpp
Fix current field highlighting in generic wxTimePickerCtrl under wxGTK.
[wxWidgets.git] / src / generic / bannerwindow.cpp
CommitLineData
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
28namespace
29{
30
31// Some constants for banner layout, currently they're hard coded but we could
32// easily make them configurable if needed later.
33const int MARGIN_X = 5;
34const int MARGIN_Y = 5;
35
36} // anonymous namespace
37
94ed214d 38const char wxBannerWindowNameStr[] = "bannerwindow";
ea11bf3a
VZ
39
40BEGIN_EVENT_TABLE(wxBannerWindow, wxWindow)
41 EVT_SIZE(wxBannerWindow::OnSize)
42 EVT_PAINT(wxBannerWindow::OnPaint)
43END_EVENT_TABLE()
44
45void wxBannerWindow::Init()
46{
47 m_direction = wxLEFT;
48
49 m_colStart = *wxWHITE;
50 m_colEnd = *wxBLUE;
51}
52
53bool
54wxBannerWindow::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
78void wxBannerWindow::SetBitmap(const wxBitmap& bmp)
79{
80 m_bitmap = bmp;
81
82 InvalidateBestSize();
83
84 Refresh();
85}
86
87void 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
97void wxBannerWindow::SetGradient(const wxColour& start, const wxColour& end)
98{
99 m_colStart = start;
100 m_colEnd = end;
101
102 Refresh();
103}
104
105wxFont wxBannerWindow::GetTitleFont() const
106{
107 wxFont font = GetFont();
108 font.MakeBold().MakeLarger();
109 return font;
110}
111
112wxSize 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
139void wxBannerWindow::OnSize(wxSizeEvent& event)
140{
141 Refresh();
142
143 event.Skip();
144}
145
146void 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
205void 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
232void
233wxBannerWindow::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