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