1///////////////////////////////////////////////////////////////////////////// 2// Name: src/univ/statusbr.cpp 3// Purpose: wxStatusBar implementation 4// Author: Vadim Zeitlin 5// Modified by: 6// Created: 14.10.01 7// RCS-ID: $Id: statusbr.cpp 42404 2006-10-25 18:14:08Z VS $ 8// Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com) 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// ============================================================================ 13// declarations 14// ============================================================================ 15 16// ---------------------------------------------------------------------------- 17// headers 18// ---------------------------------------------------------------------------- 19 20#include "wx/wxprec.h" 21 22#ifdef __BORLANDC__ 23 #pragma hdrstop 24#endif 25 26#if wxUSE_STATUSBAR 27 28#include "wx/statusbr.h" 29 30#ifndef WX_PRECOMP 31 #include "wx/settings.h" 32 #include "wx/dcclient.h" 33 #include "wx/toplevel.h" 34#endif 35 36#include "wx/univ/renderer.h" 37 38// ============================================================================ 39// implementation 40// ============================================================================ 41 42BEGIN_EVENT_TABLE(wxStatusBarUniv, wxStatusBarBase) 43 EVT_SIZE(wxStatusBarUniv::OnSize) 44 45 WX_EVENT_TABLE_INPUT_CONSUMER(wxStatusBarUniv) 46END_EVENT_TABLE() 47 48WX_FORWARD_TO_INPUT_CONSUMER(wxStatusBarUniv) 49 50// ---------------------------------------------------------------------------- 51// creation 52// ---------------------------------------------------------------------------- 53 54void wxStatusBarUniv::Init() 55{ 56} 57 58bool wxStatusBarUniv::Create(wxWindow *parent, 59 wxWindowID id, 60 long style, 61 const wxString& name) 62{ 63 if ( !wxWindow::Create(parent, id, 64 wxDefaultPosition, wxDefaultSize, 65 style, name) ) 66 { 67 return false; 68 } 69 70 SetFieldsCount(1); 71 72 CreateInputHandler(wxINP_HANDLER_STATUSBAR); 73 74 SetSize(DoGetBestSize()); 75 76 return true; 77} 78 79// ---------------------------------------------------------------------------- 80// drawing 81// ---------------------------------------------------------------------------- 82 83wxRect wxStatusBarUniv::GetTotalFieldRect(wxCoord *borderBetweenFields) 84{ 85 wxRect rect = GetClientRect(); 86 87 // no, don't do this - the borders are meant to be inside this rect 88 // wxSize sizeBorders = 89 if ( borderBetweenFields ) 90 *borderBetweenFields = m_renderer->GetStatusBarBorderBetweenFields(); 91 //rect.Deflate(sizeBorders.x, sizeBorders.y); 92 93 // recalc the field widths if needed 94 if ( m_widthsAbs.IsEmpty() ) 95 { 96 // the total width for the fields doesn't include the borders between 97 // them 98 m_widthsAbs = CalculateAbsWidths(rect.width - 99 *borderBetweenFields*(m_nFields - 1)); 100 } 101 102 return rect; 103} 104 105void wxStatusBarUniv::DoDraw(wxControlRenderer *renderer) 106{ 107 // get the fields rect 108 wxCoord borderBetweenFields; 109 wxRect rect = GetTotalFieldRect(&borderBetweenFields); 110 111 // prepare the DC 112 wxDC& dc = renderer->GetDC(); 113 dc.SetFont(GetFont()); 114 dc.SetTextForeground(GetForegroundColour()); 115 116 // do draw the fields 117 int flags = IsEnabled() ? 0 : (int)wxCONTROL_DISABLED; 118 for ( int n = 0; n < m_nFields; n++ ) 119 { 120 rect.width = m_widthsAbs[n]; 121 122 if ( IsExposed(rect) ) 123 { 124 wxTopLevelWindow *parentTLW = wxDynamicCast(GetParent(), wxTopLevelWindow); 125 126 // the size grip may be drawn only on the last field and only if we 127 // have the corresponding style and even then only if we really can 128 // resize this frame 129 if ( n == m_nFields - 1 && 130 HasFlag(wxST_SIZEGRIP) && 131 GetParent()->HasFlag(wxRESIZE_BORDER) && 132 parentTLW && !parentTLW->IsMaximized() ) 133 { 134 flags |= wxCONTROL_SIZEGRIP; 135 } 136 137 int style; 138 if (m_statusStyles) 139 style = m_statusStyles[n]; 140 else 141 style = wxSB_NORMAL; 142 m_renderer->DrawStatusField(dc, rect, m_statusText[n], flags, style); 143 } 144 145 rect.x += rect.width + borderBetweenFields; 146 } 147} 148 149void wxStatusBarUniv::RefreshField(int i) 150{ 151 wxRect rect; 152 if ( GetFieldRect(i, rect) ) 153 { 154 RefreshRect(rect); 155 } 156} 157 158// ---------------------------------------------------------------------------- 159// fields text 160// ---------------------------------------------------------------------------- 161 162void wxStatusBarUniv::SetStatusText(const wxString& text, int number) 163{ 164 wxCHECK_RET( number >= 0 && number < m_nFields, 165 _T("invalid status bar field index in SetStatusText()") ); 166 167 if ( text == m_statusText[number] ) 168 { 169 // nothing changed 170 return; 171 } 172 173 m_statusText[number] = text; 174 175 RefreshField(number); 176} 177 178wxString wxStatusBarUniv::GetStatusText(int number) const 179{ 180 wxCHECK_MSG( number >= 0 && number < m_nFields, wxEmptyString, 181 _T("invalid status bar field index") ); 182 183 return m_statusText[number]; 184} 185 186// ---------------------------------------------------------------------------- 187// fields count/widths 188// ---------------------------------------------------------------------------- 189 190void wxStatusBarUniv::SetFieldsCount(int number, const int *widths) 191{ 192 m_statusText.SetCount(number); 193 wxStatusBarBase::SetFieldsCount(number, widths); 194 m_widthsAbs.Empty(); 195} 196 197void wxStatusBarUniv::SetStatusWidths(int n, const int widths[]) 198{ 199 wxStatusBarBase::SetStatusWidths(n, widths); 200 201 m_widthsAbs.Empty(); 202} 203 204// ---------------------------------------------------------------------------- 205// geometry 206// ---------------------------------------------------------------------------- 207 208void wxStatusBarUniv::OnSize(wxSizeEvent& event) 209{ 210 // we don't need to refresh the fields whose width didn't change, so find 211 // the first field whose width did change and refresh starting from it 212 int field; 213 if ( m_statusWidths ) 214 { 215 for ( field = 0; field < m_nFields; field++ ) 216 { 217 if ( m_statusWidths[field] < 0 ) 218 { 219 // var width field 220 break; 221 } 222 } 223 } 224 else // all fields have the same width 225 { 226 // hence all fields widths have changed 227 field = 0; 228 } 229 230 if ( field < m_nFields ) 231 { 232 // call this before invalidating the old widths as we want to use them, 233 // not the new ones 234 wxRect rect = DoGetFieldRect(field); 235 236 // invalidate the widths, we'll have to recalc them 237 m_widthsAbs.Empty(); 238 239 // refresh everything after the first invalid field 240 rect.y = 0; 241 rect.SetRight(event.GetSize().x); 242 rect.height = event.GetSize().y; 243 RefreshRect(rect); 244 } 245 246 event.Skip(); 247} 248 249bool wxStatusBarUniv::GetFieldRect(int n, wxRect& rect) const 250{ 251 wxCHECK_MSG( n >= 0 && n < m_nFields, false, 252 _T("invalid field index in GetFieldRect()") ); 253 254 // this is a fix for a bug exhibited by the statbar sample: if 255 // GetFieldRect() is called from the derived class OnSize() handler, then 256 // our geometry info is wrong as our OnSize() didn't invalidate m_widthsAbs 257 // yet - so recalc it just in case 258 wxConstCast(this, wxStatusBarUniv)->m_widthsAbs.Empty(); 259 260 rect = DoGetFieldRect(n); 261 262 return true; 263} 264 265wxRect wxStatusBarUniv::DoGetFieldRect(int n) const 266{ 267 wxStatusBarUniv *self = wxConstCast(this, wxStatusBarUniv); 268 269 wxCoord borderBetweenFields; 270 wxRect rect = self->GetTotalFieldRect(&borderBetweenFields); 271 272 // it's the caller responsability to check this, if unsure - call 273 // GetFieldRect() instead 274 wxCHECK_MSG( !m_widthsAbs.IsEmpty(), rect, 275 _T("can't be called if we don't have the widths") ); 276 277 for ( int i = 0; i <= n; i++ ) 278 { 279 rect.width = m_widthsAbs[i]; 280 281 if ( i < n ) 282 rect.x += rect.width + borderBetweenFields; 283 } 284 285 return rect; 286} 287 288wxCoord wxStatusBarUniv::GetHeight() const 289{ 290 return GetCharHeight() + 2*GetBorderY(); 291} 292 293wxSize wxStatusBarUniv::DoGetBestSize() const 294{ 295 return wxSize(100, GetHeight()); 296} 297 298void wxStatusBarUniv::DoSetSize(int x, int y, 299 int width, int WXUNUSED(height), 300 int sizeFlags) 301{ 302 wxStatusBarBase::DoSetSize(x, y, width, GetHeight(), sizeFlags); 303} 304 305// ---------------------------------------------------------------------------- 306// misc 307// ---------------------------------------------------------------------------- 308 309void wxStatusBarUniv::SetMinHeight(int WXUNUSED(height)) 310{ 311 // nothing to do here, we don't support it - and why would we? 312} 313 314int wxStatusBarUniv::GetBorderX() const 315{ 316 return m_renderer->GetStatusBarBorders().x + 317 m_renderer->GetStatusBarFieldMargins().x; 318} 319 320int wxStatusBarUniv::GetBorderY() const 321{ 322 return m_renderer->GetStatusBarBorders().y + 323 m_renderer->GetStatusBarFieldMargins().y; 324} 325 326#endif // wxUSE_STATUSBAR 327