1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/generic/statusbr.cpp 
   3 // Purpose:     wxStatusBarGeneric class implementation 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  23 #include "wx/settings.h" 
  24 #include "wx/dcclient.h" 
  28 #include "wx/gtk/private.h" 
  29 #include "wx/gtk/win_gtk.h" 
  32 #include "wx/statusbr.h" 
  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 
  38 #if defined(__WXMAC__) || \ 
  39     (defined(wxUSE_NATIVE_STATUSBAR) && wxUSE_NATIVE_STATUSBAR) 
  40     #include "wx/generic/statusbr.h" 
  42     IMPLEMENT_DYNAMIC_CLASS(wxStatusBarGeneric
, wxWindow
) 
  43 #endif // wxUSE_NATIVE_STATUSBAR 
  45 BEGIN_EVENT_TABLE(wxStatusBarGeneric
, wxWindow
) 
  46     EVT_PAINT(wxStatusBarGeneric::OnPaint
) 
  47     EVT_LEFT_DOWN(wxStatusBarGeneric::OnLeftDown
) 
  48     EVT_RIGHT_DOWN(wxStatusBarGeneric::OnRightDown
) 
  49     EVT_SYS_COLOUR_CHANGED(wxStatusBarGeneric::OnSysColourChanged
) 
  52 // Default status border dimensions 
  53 #define         wxTHICK_LINE_BORDER 2 
  55 void wxStatusBarGeneric::Init() 
  57     m_borderX 
= wxTHICK_LINE_BORDER
; 
  58     m_borderY 
= wxTHICK_LINE_BORDER
; 
  61 wxStatusBarGeneric::~wxStatusBarGeneric() 
  65 bool wxStatusBarGeneric::Create(wxWindow 
*parent
, 
  70     if ( !wxWindow::Create(parent
, id
, 
  71                            wxDefaultPosition
, wxDefaultSize
, 
  72                            style 
| wxTAB_TRAVERSAL
, name
) ) 
  75     // The status bar should have a themed background 
  76     SetThemeEnabled( true ); 
  81     SetFont(*wxSMALL_FONT
); 
  84     // Set the height according to the font and the border size 
  86     dc
.SetFont(GetFont()); 
  89     dc
.GetTextExtent(_T("X"), NULL
, &y 
); 
  91     int height 
= (int)( (11*y
)/10 + 2*GetBorderY()); 
  93     SetSize(wxDefaultCoord
, wxDefaultCoord
, wxDefaultCoord
, height
); 
 101 wxSize 
wxStatusBarGeneric::DoGetBestSize() const 
 105     // best width is the width of the parent 
 106     GetParent()->GetClientSize(&width
, NULL
); 
 108     // best height is as calculated above in Create 
 109     wxClientDC 
dc((wxWindow
*)this); 
 110     dc
.SetFont(GetFont()); 
 112     dc
.GetTextExtent(_T("X"), NULL
, &y 
); 
 113     height 
= (int)( (11*y
)/10 + 2*GetBorderY()); 
 115     return wxSize(width
, height
); 
 118 void wxStatusBarGeneric::SetFieldsCount(int number
, const int *widths
) 
 120     wxASSERT_MSG( number 
>= 0, _T("negative number of fields in wxStatusBar?") ); 
 123     for(i 
= m_nFields
; i 
< number
; ++i
) 
 124         m_statusStrings
.Add( wxEmptyString 
); 
 126     for (i 
= m_nFields 
- 1; i 
>= number
; --i
) 
 127         m_statusStrings
.RemoveAt(i
); 
 129     // forget the old cached pixel widths 
 132     wxStatusBarBase::SetFieldsCount(number
, widths
); 
 134     wxASSERT_MSG( m_nFields 
== (int)m_statusStrings
.GetCount(), 
 135                   _T("This really should never happen, can we do away with m_nFields here?") ); 
 138 void wxStatusBarGeneric::SetStatusText(const wxString
& text
, int number
) 
 140     wxCHECK_RET( (number 
>= 0) && (number 
< m_nFields
), 
 141                  _T("invalid status bar field index") ); 
 143     wxString oldText 
= m_statusStrings
[number
]; 
 146         m_statusStrings
[number
] = text
; 
 149         GetFieldRect(number
, rect
); 
 151         Refresh( true, &rect 
); 
 155 wxString 
wxStatusBarGeneric::GetStatusText(int n
) const 
 157     wxCHECK_MSG( (n 
>= 0) && (n 
< m_nFields
), wxEmptyString
, 
 158                  _T("invalid status bar field index") ); 
 160     return m_statusStrings
[n
]; 
 163 void wxStatusBarGeneric::SetStatusWidths(int n
, const int widths_field
[]) 
 165     // only set status widths, when n == number of statuswindows 
 166     wxCHECK_RET( n 
== m_nFields
, _T("status bar field count mismatch") ); 
 168     // delete the old widths in any case - this function may be used to reset 
 169     // the widths to the default (all equal) 
 170     // MBN: this is incompatible with at least wxMSW and wxMAC and not 
 171     //      documented, but let's keep it for now 
 174     // forget the old cached pixel widths 
 179         // not an error, see the comment above 
 184     wxStatusBarBase::SetStatusWidths(n
, widths_field
); 
 187 void wxStatusBarGeneric::OnPaint(wxPaintEvent
& WXUNUSED(event
) ) 
 193     if (HasFlag( wxST_SIZEGRIP 
)) 
 196         GetClientSize(&width
, &height
); 
 198         gtk_paint_resize_grip( m_widget
->style
, 
 199                                GTK_PIZZA(m_wxwindow
)->bin_window
, 
 200                                (GtkStateType
) GTK_WIDGET_STATE (m_widget
), 
 204                                GDK_WINDOW_EDGE_SOUTH_EAST
, 
 205                                width
-height
-2, 1, height
-2, height
-3 ); 
 211         dc
.SetFont(GetFont()); 
 213     dc
.SetBackgroundMode(wxTRANSPARENT
); 
 218     vColor 
= wxSystemSettings::GetColour(wxSYS_COLOUR_MENUBAR
); 
 219     ::WinFillRect(dc
.m_hPS
, &dc
.m_vRclPaint
, vColor
.GetPixel()); 
 222     for (int i 
= 0; i 
< m_nFields
; i 
++) 
 226 void wxStatusBarGeneric::DrawFieldText(wxDC
& dc
, int i
) 
 231     GetFieldRect(i
, rect
); 
 233     wxString 
text(GetStatusText(i
)); 
 237     dc
.GetTextExtent(text
, &x
, &y
); 
 239     int xpos 
= rect
.x 
+ leftMargin
; 
 240     int ypos 
= (int) (((rect
.height 
- y
) / 2 ) + rect
.y 
+ 0.5) ; 
 242 #if defined( __WXGTK__ ) || defined(__WXMAC__) 
 247     dc
.SetClippingRegion(rect
.x
, rect
.y
, rect
.width
, rect
.height
); 
 249     dc
.DrawText(text
, xpos
, ypos
); 
 251     dc
.DestroyClippingRegion(); 
 254 void wxStatusBarGeneric::DrawField(wxDC
& dc
, int i
) 
 257     GetFieldRect(i
, rect
); 
 259     int style 
= wxSB_NORMAL
; 
 261         style 
= m_statusStyles
[i
]; 
 263     if (style 
!= wxSB_FLAT
) 
 267         // Have grey background, plus 3-d border - 
 268         // One black rectangle. 
 269         // Inside this, left and top sides - dark grey. Bottom and right - 
 271         // Reverse it for wxSB_RAISED 
 273         dc
.SetPen((style 
== wxSB_RAISED
) ? m_mediumShadowPen 
: m_hilightPen
); 
 277         // Right and bottom lines 
 278         dc
.DrawLine(rect
.x 
+ rect
.width
, rect
.y
, 
 279                     rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height
); 
 280         dc
.DrawLine(rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height
, 
 281                     rect
.x
, rect
.y 
+ rect
.height
); 
 283         dc
.SetPen((style 
== wxSB_RAISED
) ? m_hilightPen 
: m_mediumShadowPen
); 
 285         // Left and top lines 
 286         dc
.DrawLine(rect
.x
, rect
.y 
+ rect
.height
, 
 288         dc
.DrawLine(rect
.x
, rect
.y
, 
 289             rect
.x 
+ rect
.width
, rect
.y
); 
 292         dc
.DrawLine(rect
.x 
+ rect
.width
, rect
.height 
+ 2, 
 293                     rect
.x
, rect
.height 
+ 2); 
 294         dc
.DrawLine(rect
.x 
+ rect
.width
, rect
.y
, 
 295                     rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height
); 
 297         dc
.SetPen((style 
== wxSB_RAISED
) ? m_hilightPen 
: m_mediumShadowPen
); 
 298         dc
.DrawLine(rect
.x
, rect
.y
, 
 299                     rect
.x 
+ rect
.width
, rect
.y
); 
 300         dc
.DrawLine(rect
.x
, rect
.y 
+ rect
.height
, 
 306     DrawFieldText(dc
, i
); 
 309   // Get the position and size of the field's internal bounding rectangle 
 310 bool wxStatusBarGeneric::GetFieldRect(int n
, wxRect
& rect
) const 
 312     wxCHECK_MSG( (n 
>= 0) && (n 
< m_nFields
), false, 
 313                  _T("invalid status bar field index") ); 
 315     // FIXME: workarounds for OS/2 bugs have nothing to do here (VZ) 
 318     GetSize(&width
, &height
); 
 320     GetClientSize(&width
, &height
); 
 323     // we cache m_widthsAbs between calls and recompute it if client 
 324     // width has changed (or when it is initially empty) 
 325     if ( m_widthsAbs
.IsEmpty() || (m_lastClientWidth 
!= width
) ) 
 327         wxConstCast(this, wxStatusBarGeneric
)-> 
 328             m_widthsAbs 
= CalculateAbsWidths(width
); 
 329         // remember last width for which we have recomputed the widths in pixels 
 330         wxConstCast(this, wxStatusBarGeneric
)-> 
 331             m_lastClientWidth 
= width
; 
 335     for ( int i 
= 0; i 
< n
; i
++ ) 
 337         rect
.x 
+= m_widthsAbs
[i
]; 
 343     rect
.width 
= m_widthsAbs
[n
] - 2*m_borderX
; 
 344     rect
.height 
= height 
- 2*m_borderY
; 
 349 // Initialize colours 
 350 void wxStatusBarGeneric::InitColours() 
 353 #if defined(__WXMSW__) || defined(__WXMAC__) 
 354     wxColour 
mediumShadowColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
)); 
 355     m_mediumShadowPen 
= wxPen(mediumShadowColour
, 1, wxSOLID
); 
 357     wxColour 
hilightColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DHILIGHT
)); 
 358     m_hilightPen 
= wxPen(hilightColour
, 1, wxSOLID
); 
 359 #elif defined(__WXPM__) 
 360     m_mediumShadowPen 
= wxPen(wxColour(127, 127, 127), 1, wxSOLID
); 
 361     m_hilightPen 
= wxPen(_T("WHITE"), 1, wxSOLID
); 
 365     vColour
.Set(wxString(_T("LIGHT GREY"))); 
 366     SetBackgroundColour(vColour
); 
 367     vColour
.Set(wxString(_T("BLACK"))); 
 368     SetForegroundColour(vColour
); 
 370     m_mediumShadowPen 
= wxPen("GREY", 1, wxSOLID
); 
 371     m_hilightPen 
= wxPen("WHITE", 1, wxSOLID
); 
 375 // Responds to colour changes, and passes event on to children. 
 376 void wxStatusBarGeneric::OnSysColourChanged(wxSysColourChangedEvent
& event
) 
 380     // Propagate the event to the non-top-level children 
 381     wxWindow::OnSysColourChanged(event
); 
 384 void wxStatusBarGeneric::SetMinHeight(int height
) 
 386     // check that this min height is not less than minimal height for the 
 390     dc
.GetTextExtent( wxT("X"), NULL
, &y 
); 
 392     if ( height 
> (11*y
)/10 ) 
 394         SetSize(wxDefaultCoord
, wxDefaultCoord
, wxDefaultCoord
, height 
+ 2*m_borderY
); 
 398 void wxStatusBarGeneric::OnLeftDown(wxMouseEvent
& event
) 
 402     GetClientSize(&width
, &height
); 
 404     if (HasFlag( wxST_SIZEGRIP 
) && (event
.GetX() > width
-height
)) 
 406         GtkWidget 
*ancestor 
= gtk_widget_get_toplevel( m_widget 
); 
 408         if (!GTK_IS_WINDOW (ancestor
)) 
 411         GdkWindow 
*source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
 415         gdk_window_get_origin( source
, &org_x
, &org_y 
); 
 417         gtk_window_begin_resize_drag (GTK_WINDOW (ancestor
), 
 418                                   GDK_WINDOW_EDGE_SOUTH_EAST
, 
 420                                   org_x 
+ event
.GetX(), 
 421                                   org_y 
+ event
.GetY(), 
 433 void wxStatusBarGeneric::OnRightDown(wxMouseEvent
& event
) 
 437     GetClientSize(&width
, &height
); 
 439     if (HasFlag( wxST_SIZEGRIP 
) && (event
.GetX() > width
-height
)) 
 441         GtkWidget 
*ancestor 
= gtk_widget_get_toplevel( m_widget 
); 
 443         if (!GTK_IS_WINDOW (ancestor
)) 
 446         GdkWindow 
*source 
= GTK_PIZZA(m_wxwindow
)->bin_window
; 
 450         gdk_window_get_origin( source
, &org_x
, &org_y 
); 
 452         gtk_window_begin_move_drag (GTK_WINDOW (ancestor
), 
 454                                 org_x 
+ event
.GetX(), 
 455                                 org_y 
+ event
.GetY(), 
 467 #endif // wxUSE_STATUSBAR