]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/generic/statusbr.cpp
don't use wxVector<wxDataFormat> from wx/clipbrd.h as wxDataFormat definition is...
[wxWidgets.git] / src / generic / statusbr.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/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
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16 #pragma hdrstop
17#endif
18
19#if wxUSE_STATUSBAR
20
21#include "wx/statusbr.h"
22
23#ifndef WX_PRECOMP
24 #include "wx/settings.h"
25 #include "wx/dcclient.h"
26 #include "wx/toplevel.h"
27#endif
28
29#ifdef __WXGTK20__
30 #include <gtk/gtk.h>
31#endif
32
33// we only have to do it here when we use wxStatusBarGeneric in addition to the
34// standard wxStatusBar class, if wxStatusBarGeneric is the same as
35// wxStatusBar, then the corresponding IMPLEMENT_DYNAMIC_CLASS is already in
36// common/statbar.cpp
37#if defined(__WXMAC__) || \
38 (defined(wxUSE_NATIVE_STATUSBAR) && wxUSE_NATIVE_STATUSBAR)
39 #include "wx/generic/statusbr.h"
40
41 IMPLEMENT_DYNAMIC_CLASS(wxStatusBarGeneric, wxWindow)
42#endif // wxUSE_NATIVE_STATUSBAR
43
44// Default status border dimensions
45#define wxTHICK_LINE_BORDER 2
46
47
48// ----------------------------------------------------------------------------
49// wxStatusBarGeneric
50// ----------------------------------------------------------------------------
51
52BEGIN_EVENT_TABLE(wxStatusBarGeneric, wxWindow)
53 EVT_PAINT(wxStatusBarGeneric::OnPaint)
54 EVT_LEFT_DOWN(wxStatusBarGeneric::OnLeftDown)
55 EVT_RIGHT_DOWN(wxStatusBarGeneric::OnRightDown)
56 EVT_SYS_COLOUR_CHANGED(wxStatusBarGeneric::OnSysColourChanged)
57END_EVENT_TABLE()
58
59void wxStatusBarGeneric::Init()
60{
61 m_borderX = wxTHICK_LINE_BORDER;
62 m_borderY = wxTHICK_LINE_BORDER;
63}
64
65wxStatusBarGeneric::~wxStatusBarGeneric()
66{
67}
68
69bool wxStatusBarGeneric::Create(wxWindow *parent,
70 wxWindowID id,
71 long style,
72 const wxString& name)
73{
74 style |= wxTAB_TRAVERSAL | wxFULL_REPAINT_ON_RESIZE;
75 if ( !wxWindow::Create(parent, id,
76 wxDefaultPosition, wxDefaultSize,
77 style, name) )
78 return false;
79
80 // The status bar should have a themed background
81 SetThemeEnabled( true );
82
83 InitColours();
84
85#ifdef __WXPM__
86 SetFont(*wxSMALL_FONT);
87#endif
88
89 wxCoord y;
90 {
91 // Set the height according to the font and the border size
92 wxClientDC dc(this);
93 dc.SetFont(GetFont());
94
95 dc.GetTextExtent(_T("X"), NULL, &y );
96 }
97 int height = (int)( (11*y)/10 + 2*GetBorderY());
98
99 SetSize(wxDefaultCoord, wxDefaultCoord, wxDefaultCoord, height);
100
101 SetFieldsCount(1);
102
103 return true;
104}
105
106wxSize wxStatusBarGeneric::DoGetBestSize() const
107{
108 int width, height;
109
110 // best width is the width of the parent
111 GetParent()->GetClientSize(&width, NULL);
112
113 // best height is as calculated above in Create
114 wxClientDC dc((wxWindow*)this);
115 dc.SetFont(GetFont());
116 wxCoord y;
117 dc.GetTextExtent(_T("X"), NULL, &y );
118 height = (int)( (11*y)/10 + 2*GetBorderY());
119
120 return wxSize(width, height);
121}
122
123void wxStatusBarGeneric::SetFieldsCount(int number, const int *widths)
124{
125 wxASSERT_MSG( number >= 0, _T("negative number of fields in wxStatusBar?") );
126
127 // enlarge the m_statusStrings array if needed:
128 for (size_t i = m_panes.GetCount(); i < (size_t)number; ++i)
129 m_statusStrings.Add( wxEmptyString );
130
131 // shrink the m_statusStrings array if needed:
132 for (int j = (int)m_panes.GetCount() - 1; j >= number; --j)
133 m_statusStrings.RemoveAt(j);
134
135 // forget the old cached pixel widths
136 m_widthsAbs.Empty();
137
138 wxStatusBarBase::SetFieldsCount(number, widths);
139
140 wxASSERT_MSG( m_panes.GetCount() == m_statusStrings.GetCount(),
141 _T("This really should never happen, can we do away with m_panes.GetCount() here?") );
142}
143
144void wxStatusBarGeneric::SetStatusText(const wxString& text, int number)
145{
146 wxCHECK_RET( (number >= 0) && ((size_t)number < m_panes.GetCount()),
147 _T("invalid status bar field index") );
148
149 wxString oldText = m_statusStrings[number];
150 if (oldText != text)
151 {
152 m_statusStrings[number] = text;
153
154 wxRect rect;
155 GetFieldRect(number, rect);
156
157 Refresh(true, &rect);
158
159 // it's common to show some text in the status bar before starting a
160 // relatively lengthy operation, ensure that the text is shown to the
161 // user immediately and not after the lengthy operation end
162 Update();
163 }
164}
165
166wxString wxStatusBarGeneric::GetStatusText(int n) const
167{
168 wxCHECK_MSG( (n >= 0) && ((size_t)n < m_panes.GetCount()), wxEmptyString,
169 _T("invalid status bar field index") );
170
171 return m_statusStrings[n];
172}
173
174void wxStatusBarGeneric::SetStatusWidths(int n, const int widths_field[])
175{
176 // only set status widths when n == number of statuswindows
177 wxCHECK_RET( (size_t)n == m_panes.GetCount(), _T("status bar field count mismatch") );
178
179 // forget the old cached pixel widths
180 m_widthsAbs.Empty();
181
182 wxStatusBarBase::SetStatusWidths(n, widths_field);
183}
184
185bool wxStatusBarGeneric::ShowsSizeGrip() const
186{
187 if ( !HasFlag(wxST_SIZEGRIP) )
188 return false;
189
190 wxTopLevelWindow * const
191 tlw = wxDynamicCast(wxGetTopLevelParent(GetParent()), wxTopLevelWindow);
192 return tlw && !tlw->IsMaximized() && tlw->HasFlag(wxRESIZE_BORDER);
193}
194
195void wxStatusBarGeneric::OnPaint(wxPaintEvent& WXUNUSED(event) )
196{
197 wxPaintDC dc(this);
198
199#ifdef __WXGTK20__
200 // Draw grip first
201 if ( ShowsSizeGrip() )
202 {
203 int width, height;
204 GetClientSize(&width, &height);
205
206 if (GetLayoutDirection() == wxLayout_RightToLeft)
207 {
208 gtk_paint_resize_grip( m_widget->style,
209 GTKGetDrawingWindow(),
210 (GtkStateType) GTK_WIDGET_STATE (m_widget),
211 NULL,
212 m_widget,
213 "statusbar",
214 GDK_WINDOW_EDGE_SOUTH_WEST,
215 2, 2, height-2, height-4 );
216 }
217 else
218 {
219 gtk_paint_resize_grip( m_widget->style,
220 GTKGetDrawingWindow(),
221 (GtkStateType) GTK_WIDGET_STATE (m_widget),
222 NULL,
223 m_widget,
224 "statusbar",
225 GDK_WINDOW_EDGE_SOUTH_EAST,
226 width-height-2, 2, height-2, height-4 );
227 }
228 }
229#endif // __WXGTK20__
230
231 if (GetFont().Ok())
232 dc.SetFont(GetFont());
233
234 dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
235
236 for (size_t i = 0; i < m_panes.GetCount(); i ++)
237 DrawField(dc, i);
238}
239
240void wxStatusBarGeneric::DrawFieldText(wxDC& dc, int i)
241{
242 int leftMargin = 2;
243
244 wxRect rect;
245 GetFieldRect(i, rect);
246
247 wxString text(GetStatusText(i));
248
249 wxCoord x = 0, y = 0;
250
251 dc.GetTextExtent(text, &x, &y);
252
253 int xpos = rect.x + leftMargin;
254 int ypos = (int) (((rect.height - y) / 2 ) + rect.y + 0.5) ;
255
256#if defined( __WXGTK__ ) || defined(__WXMAC__)
257 xpos++;
258 ypos++;
259#endif
260
261 dc.SetClippingRegion(rect.x, rect.y, rect.width, rect.height);
262
263 dc.DrawText(text, xpos, ypos);
264
265 dc.DestroyClippingRegion();
266}
267
268void wxStatusBarGeneric::DrawField(wxDC& dc, int i)
269{
270 wxRect rect;
271 GetFieldRect(i, rect);
272
273 int style = m_panes[i].nStyle;
274 if (style != wxSB_FLAT)
275 {
276 // Draw border
277 // For wxSB_NORMAL:
278 // Have grey background, plus 3-d border -
279 // One black rectangle.
280 // Inside this, left and top sides - dark grey. Bottom and right -
281 // white.
282 // Reverse it for wxSB_RAISED
283
284 dc.SetPen((style == wxSB_RAISED) ? m_mediumShadowPen : m_hilightPen);
285
286 #ifndef __WXPM__
287
288 // Right and bottom lines
289 dc.DrawLine(rect.x + rect.width, rect.y,
290 rect.x + rect.width, rect.y + rect.height);
291 dc.DrawLine(rect.x + rect.width, rect.y + rect.height,
292 rect.x, rect.y + rect.height);
293
294 dc.SetPen((style == wxSB_RAISED) ? m_hilightPen : m_mediumShadowPen);
295
296 // Left and top lines
297 dc.DrawLine(rect.x, rect.y + rect.height,
298 rect.x, rect.y);
299 dc.DrawLine(rect.x, rect.y,
300 rect.x + rect.width, rect.y);
301 #else
302
303 dc.DrawLine(rect.x + rect.width, rect.height + 2,
304 rect.x, rect.height + 2);
305 dc.DrawLine(rect.x + rect.width, rect.y,
306 rect.x + rect.width, rect.y + rect.height);
307
308 dc.SetPen((style == wxSB_RAISED) ? m_hilightPen : m_mediumShadowPen);
309 dc.DrawLine(rect.x, rect.y,
310 rect.x + rect.width, rect.y);
311 dc.DrawLine(rect.x, rect.y + rect.height,
312 rect.x, rect.y);
313
314#endif
315 }
316
317 DrawFieldText(dc, i);
318}
319
320 // Get the position and size of the field's internal bounding rectangle
321bool wxStatusBarGeneric::GetFieldRect(int n, wxRect& rect) const
322{
323 wxCHECK_MSG( (n >= 0) && ((size_t)n < m_panes.GetCount()), false,
324 _T("invalid status bar field index") );
325
326 // FIXME: workarounds for OS/2 bugs have nothing to do here (VZ)
327 int width, height;
328#ifdef __WXPM__
329 GetSize(&width, &height);
330#else
331 GetClientSize(&width, &height);
332#endif
333
334 // we cache m_widthsAbs between calls and recompute it if client
335 // width has changed (or when it is initially empty)
336 if ( m_widthsAbs.IsEmpty() || (m_lastClientWidth != width) )
337 {
338 wxConstCast(this, wxStatusBarGeneric)->
339 m_widthsAbs = CalculateAbsWidths(width);
340 // remember last width for which we have recomputed the widths in pixels
341 wxConstCast(this, wxStatusBarGeneric)->
342 m_lastClientWidth = width;
343 }
344
345 rect.x = 0;
346 for ( int i = 0; i < n; i++ )
347 {
348 rect.x += m_widthsAbs[i];
349 }
350
351 rect.x += m_borderX;
352 rect.y = m_borderY;
353
354 rect.width = m_widthsAbs[n] - 2*m_borderX;
355 rect.height = height - 2*m_borderY;
356
357 return true;
358}
359
360// Initialize colours
361void wxStatusBarGeneric::InitColours()
362{
363#if defined(__WXPM__)
364 m_mediumShadowPen = wxPen(wxColour(127, 127, 127), 1, wxSOLID);
365 m_hilightPen = *wxWHITE_PEN;
366
367 SetBackgroundColour(*wxLIGHT_GREY);
368 SetForegroundColour(*wxBLACK);
369#else // !__WXPM__
370 m_mediumShadowPen = wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW));
371 m_hilightPen = wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DHILIGHT));
372#endif // __WXPM__/!__WXPM__
373}
374
375// Responds to colour changes, and passes event on to children.
376void wxStatusBarGeneric::OnSysColourChanged(wxSysColourChangedEvent& event)
377{
378 InitColours();
379
380 // Propagate the event to the non-top-level children
381 wxWindow::OnSysColourChanged(event);
382}
383
384void wxStatusBarGeneric::SetMinHeight(int height)
385{
386 // check that this min height is not less than minimal height for the
387 // current font
388 wxClientDC dc(this);
389 wxCoord y;
390 dc.GetTextExtent( wxT("X"), NULL, &y );
391
392 if ( height > (11*y)/10 )
393 {
394 SetSize(wxDefaultCoord, wxDefaultCoord, wxDefaultCoord, height + 2*m_borderY);
395 }
396}
397
398void wxStatusBarGeneric::OnLeftDown(wxMouseEvent& event)
399{
400#ifdef __WXGTK20__
401 int width, height;
402 GetClientSize(&width, &height);
403
404 if ( ShowsSizeGrip() && (event.GetX() > width-height) )
405 {
406 GtkWidget *ancestor = gtk_widget_get_toplevel( m_widget );
407
408 if (!GTK_IS_WINDOW (ancestor))
409 return;
410
411 GdkWindow *source = GTKGetDrawingWindow();
412
413 int org_x = 0;
414 int org_y = 0;
415 gdk_window_get_origin( source, &org_x, &org_y );
416
417 if (GetLayoutDirection() == wxLayout_RightToLeft)
418 {
419 gtk_window_begin_resize_drag (GTK_WINDOW (ancestor),
420 GDK_WINDOW_EDGE_SOUTH_WEST,
421 1,
422 org_x - event.GetX() + GetSize().x ,
423 org_y + event.GetY(),
424 0);
425 }
426 else
427 {
428 gtk_window_begin_resize_drag (GTK_WINDOW (ancestor),
429 GDK_WINDOW_EDGE_SOUTH_EAST,
430 1,
431 org_x + event.GetX(),
432 org_y + event.GetY(),
433 0);
434 }
435 }
436 else
437 {
438 event.Skip( true );
439 }
440#else
441 event.Skip( true );
442#endif
443}
444
445void wxStatusBarGeneric::OnRightDown(wxMouseEvent& event)
446{
447#ifdef __WXGTK20__
448 int width, height;
449 GetClientSize(&width, &height);
450
451 if ( ShowsSizeGrip() && (event.GetX() > width-height) )
452 {
453 GtkWidget *ancestor = gtk_widget_get_toplevel( m_widget );
454
455 if (!GTK_IS_WINDOW (ancestor))
456 return;
457
458 GdkWindow *source = GTKGetDrawingWindow();
459
460 int org_x = 0;
461 int org_y = 0;
462 gdk_window_get_origin( source, &org_x, &org_y );
463
464 gtk_window_begin_move_drag (GTK_WINDOW (ancestor),
465 2,
466 org_x + event.GetX(),
467 org_y + event.GetY(),
468 0);
469 }
470 else
471 {
472 event.Skip( true );
473 }
474#else
475 event.Skip( true );
476#endif
477}
478
479#endif // wxUSE_STATUSBAR