generic status bar now:
[wxWidgets.git] / src / generic / statusbr.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: generic/statusbr.cpp
3 // Purpose: wxStatusBarGeneric class implementation
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 01/02/97
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "statusbr.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #if wxUSE_STATUSBAR
24
25 #ifndef WX_PRECOMP
26 #include "wx/setup.h"
27 #include "wx/frame.h"
28 #include "wx/settings.h"
29 #include "wx/dcclient.h"
30 #endif
31
32 #include "wx/statusbr.h"
33
34 // we only have to do it here when we use wxStatusBarGeneric in addition to the
35 // standard wxStatusBar class, if wxStatusBarGeneric is the same as
36 // wxStatusBar, then the corresponding IMPLEMENT_DYNAMIC_CLASS is already in
37 // common/statbar.cpp
38 #if defined(__WXMAC__) || \
39 (defined(wxUSE_NATIVE_STATUSBAR) && wxUSE_NATIVE_STATUSBAR)
40 #include "wx/generic/statusbr.h"
41
42 IMPLEMENT_DYNAMIC_CLASS(wxStatusBarGeneric, wxWindow)
43 #endif // wxUSE_NATIVE_STATUSBAR
44
45 BEGIN_EVENT_TABLE(wxStatusBarGeneric, wxWindow)
46 EVT_PAINT(wxStatusBarGeneric::OnPaint)
47 EVT_SIZE(wxStatusBarGeneric::OnSize)
48
49 EVT_SYS_COLOUR_CHANGED(wxStatusBarGeneric::OnSysColourChanged)
50 END_EVENT_TABLE()
51
52 // Default status border dimensions
53 #define wxTHICK_LINE_BORDER 2
54 #define wxTHICK_LINE_WIDTH 1
55
56 void wxStatusBarGeneric::Init()
57 {
58 m_borderX = wxTHICK_LINE_BORDER;
59 m_borderY = wxTHICK_LINE_BORDER;
60 }
61
62 wxStatusBarGeneric::~wxStatusBarGeneric()
63 {
64 // VZ: what is this for? please comment...
65 #ifdef __WXMSW__
66 SetFont(wxNullFont);
67 #endif // MSW
68 }
69
70 bool wxStatusBarGeneric::Create(wxWindow *parent,
71 wxWindowID id,
72 long style,
73 const wxString& name)
74 {
75 if ( !wxWindow::Create(parent, id,
76 wxDefaultPosition, wxDefaultSize,
77 style | wxTAB_TRAVERSAL, name) )
78 return FALSE;
79
80 // The status bar should have a themed background
81 SetThemeEnabled( TRUE );
82
83 // Don't wish this to be found as a child
84 #ifndef __WXMAC__
85 parent->GetChildren().DeleteObject(this);
86 #endif
87 InitColours();
88
89 SetFont(m_defaultStatusBarFont);
90
91 // Set the height according to the font and the border size
92 wxClientDC dc(this);
93 dc.SetFont(GetFont());
94
95 wxCoord y;
96 dc.GetTextExtent(_T("X"), NULL, &y );
97
98 int height = (int)( (11*y)/10 + 2*GetBorderY());
99
100 SetSize(-1, -1, -1, height);
101
102 return TRUE;
103 }
104
105 void wxStatusBarGeneric::SetFieldsCount(int number, const int *widths)
106 {
107 wxASSERT_MSG( number >= 0, _T("negative number of fields in wxStatusBar?") );
108
109 int i;
110 for(i = m_nFields; i < number; ++i)
111 m_statusStrings.Add( wxEmptyString );
112
113 for (i = m_nFields - 1; i >= number; --i)
114 m_statusStrings.RemoveAt(i);
115
116 m_nFields = number;
117
118 wxASSERT_MSG( m_nFields == (int)m_statusStrings.GetCount(),
119 _T("This really should never happen, can we do away with m_nFields here?") );
120
121 SetStatusWidths(number, widths);
122 }
123
124 void wxStatusBarGeneric::SetStatusText(const wxString& text, int number)
125 {
126 wxCHECK_RET( (number >= 0) && (number < m_nFields),
127 _T("invalid status bar field index") );
128
129 m_statusStrings[number] = text;
130
131 wxRect rect;
132 GetFieldRect(number, rect);
133
134 Refresh( TRUE, &rect );
135 }
136
137 wxString wxStatusBarGeneric::GetStatusText(int n) const
138 {
139 wxCHECK_MSG( (n >= 0) && (n < m_nFields), wxEmptyString,
140 _T("invalid status bar field index") );
141
142 return m_statusStrings[n];
143 }
144
145 void wxStatusBarGeneric::SetStatusWidths(int n, const int widths_field[])
146 {
147 // only set status widths, when n == number of statuswindows
148 wxCHECK_RET( n == m_nFields, _T("status bar field count mismatch") );
149
150 // delete the old widths in any case - this function may be used to reset
151 // the widths to the default (all equal)
152 // MBN: this is incompatible with at least wxMSW and wxMAC and not
153 // documented, but let's keep it for now
154 ReinitWidths();
155
156 // forget the old cached pixel widths
157 m_widthsAbs.Empty();
158
159 if ( !widths_field )
160 {
161 // not an error, see the comment above
162 Refresh();
163 return;
164 }
165
166 wxStatusBarBase::SetStatusWidths(n, widths_field);
167 }
168
169 void wxStatusBarGeneric::OnPaint(wxPaintEvent& WXUNUSED(event) )
170 {
171 wxPaintDC dc(this);
172
173
174 int i;
175 if ( GetFont().Ok() )
176 dc.SetFont(GetFont());
177 dc.SetBackgroundMode(wxTRANSPARENT);
178
179 #ifdef __WXPM__
180 wxColour vColor;
181
182 vColor = wxSystemSettings::GetColour(wxSYS_COLOUR_MENUBAR);
183 ::WinFillRect(dc.m_hPS, &dc.m_vRclPaint, vColor.GetPixel());
184 #endif
185
186 for ( i = 0; i < m_nFields; i ++ )
187 DrawField(dc, i);
188
189 // VZ: again, what is this for?
190 #ifdef __WXMSW__
191 dc.SetFont(wxNullFont);
192 #endif // MSW
193 }
194
195 void wxStatusBarGeneric::DrawFieldText(wxDC& dc, int i)
196 {
197 int leftMargin = 2;
198
199 wxRect rect;
200 GetFieldRect(i, rect);
201
202 wxString text(GetStatusText(i));
203
204 long x, y;
205
206 dc.GetTextExtent(text, &x, &y);
207
208 int xpos = rect.x + leftMargin;
209 int ypos = (int) (((rect.height - y) / 2 ) + rect.y + 0.5) ;
210
211 #if defined( __WXGTK__ ) || defined(__WXMAC__)
212 xpos++;
213 ypos++;
214 #endif
215
216 dc.SetClippingRegion(rect.x, rect.y, rect.width, rect.height);
217
218 dc.DrawText(text, xpos, ypos);
219
220 dc.DestroyClippingRegion();
221 }
222
223 void wxStatusBarGeneric::DrawField(wxDC& dc, int i)
224 {
225 wxRect rect;
226 GetFieldRect(i, rect);
227
228 // Draw border
229 // Have grey background, plus 3-d border -
230 // One black rectangle.
231 // Inside this, left and top sides - dark grey. Bottom and right -
232 // white.
233
234 dc.SetPen(m_hilightPen);
235
236 #ifndef __WXPM__
237
238 // Right and bottom white lines
239 dc.DrawLine(rect.x + rect.width, rect.y,
240 rect.x + rect.width, rect.y + rect.height);
241 dc.DrawLine(rect.x + rect.width, rect.y + rect.height,
242 rect.x, rect.y + rect.height);
243
244 dc.SetPen(m_mediumShadowPen);
245
246 // Left and top grey lines
247 dc.DrawLine(rect.x, rect.y + rect.height,
248 rect.x, rect.y);
249 dc.DrawLine(rect.x, rect.y,
250 rect.x + rect.width, rect.y);
251 #else
252
253 dc.DrawLine(rect.x + rect.width, rect.height + 2,
254 rect.x, rect.height + 2);
255 dc.DrawLine(rect.x + rect.width, rect.y,
256 rect.x + rect.width, rect.y + rect.height);
257
258 dc.SetPen(m_mediumShadowPen);
259 dc.DrawLine(rect.x, rect.y,
260 rect.x + rect.width, rect.y);
261 dc.DrawLine(rect.x, rect.y + rect.height,
262 rect.x, rect.y);
263
264 #endif
265
266 DrawFieldText(dc, i);
267 }
268
269 // Get the position and size of the field's internal bounding rectangle
270 bool wxStatusBarGeneric::GetFieldRect(int n, wxRect& rect) const
271 {
272 wxCHECK_MSG( (n >= 0) && (n < m_nFields), FALSE,
273 _T("invalid status bar field index") );
274
275 // FIXME: workarounds for OS/2 bugs have nothing to do here (VZ)
276 int width, height;
277 #ifdef __WXPM__
278 GetSize(&width, &height);
279 #else
280 GetClientSize(&width, &height);
281 #endif
282
283 // we cache m_widthsAbs between calls normally but it's cleared when the
284 // status widths change so recompute it if needed
285 if ( m_widthsAbs.IsEmpty() )
286 {
287 wxConstCast(this, wxStatusBarGeneric)->
288 m_widthsAbs = CalculateAbsWidths(width);
289 }
290
291 rect.x = 0;
292 for ( int i = 0; i < n; i++ )
293 {
294 rect.x += m_widthsAbs[i];
295 }
296
297 rect.x += m_borderX;
298 rect.y = m_borderY;
299
300 rect.width = m_widthsAbs[n] - 2*m_borderX;
301 rect.height = height - 2*m_borderY;
302
303 return TRUE;
304 }
305
306 // Initialize colours
307 void wxStatusBarGeneric::InitColours()
308 {
309 // Shadow colours
310 #if defined(__WIN95__)
311 wxColour mediumShadowColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW));
312 m_mediumShadowPen = wxPen(mediumShadowColour, 1, wxSOLID);
313
314 wxColour hilightColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DHILIGHT));
315 m_hilightPen = wxPen(hilightColour, 1, wxSOLID);
316 #elif defined(__WXPM__)
317 m_mediumShadowPen = wxPen(wxColour(127, 127, 127), 1, wxSOLID);
318 m_hilightPen = wxPen("WHITE", 1, wxSOLID);
319
320 wxColour vColour;
321
322 vColour.Set(wxString("LIGHT GREY"));
323 SetBackgroundColour(vColour);
324 vColour.Set(wxString("BLACK"));
325 SetForegroundColour(vColour);
326 m_defaultStatusBarFont = *wxSMALL_FONT;
327 #else
328 m_mediumShadowPen = wxPen("GREY", 1, wxSOLID);
329 m_hilightPen = wxPen("WHITE", 1, wxSOLID);
330 #endif
331
332 #ifndef __WXPM__
333 m_defaultStatusBarFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
334 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
335 #endif
336 }
337
338 // Responds to colour changes, and passes event on to children.
339 void wxStatusBarGeneric::OnSysColourChanged(wxSysColourChangedEvent& event)
340 {
341 InitColours();
342 Refresh();
343
344 // Propagate the event to the non-top-level children
345 wxWindow::OnSysColourChanged(event);
346 }
347
348 void wxStatusBarGeneric::SetMinHeight(int height)
349 {
350 // check that this min height is not less than minimal height for the
351 // current font
352 wxClientDC dc(this);
353 wxCoord y;
354 dc.GetTextExtent( _T("X"), NULL, &y );
355
356 if ( height > (11*y)/10 )
357 {
358 SetSize(-1, -1, -1, height + 2*m_borderY);
359 }
360 }
361
362 void wxStatusBarGeneric::OnSize(wxSizeEvent& event)
363 {
364 // have to recompute the widths in pixels
365 m_widthsAbs.Empty();
366
367 event.Skip();
368 }
369
370 #endif // wxUSE_STATUSBAR
371