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"
21 #include "wx/statusbr.h"
24 #include "wx/settings.h"
25 #include "wx/dcclient.h"
26 #include "wx/toplevel.h"
27 #include "wx/control.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 // Default status border dimensions
46 #define wxTHICK_LINE_BORDER 2
48 // Margin between the field text and the field rect
49 #define wxFIELD_TEXT_MARGIN 2
52 // ----------------------------------------------------------------------------
54 // ----------------------------------------------------------------------------
56 BEGIN_EVENT_TABLE(wxStatusBarGeneric
, wxWindow
)
57 EVT_PAINT(wxStatusBarGeneric::OnPaint
)
58 EVT_SIZE(wxStatusBarGeneric::OnSize
)
59 EVT_LEFT_DOWN(wxStatusBarGeneric::OnLeftDown
)
60 EVT_RIGHT_DOWN(wxStatusBarGeneric::OnRightDown
)
61 EVT_SYS_COLOUR_CHANGED(wxStatusBarGeneric::OnSysColourChanged
)
64 void wxStatusBarGeneric::Init()
66 m_borderX
= wxTHICK_LINE_BORDER
;
67 m_borderY
= wxTHICK_LINE_BORDER
;
70 wxStatusBarGeneric::~wxStatusBarGeneric()
74 bool wxStatusBarGeneric::Create(wxWindow
*parent
,
79 style
|= wxTAB_TRAVERSAL
| wxFULL_REPAINT_ON_RESIZE
;
80 if ( !wxWindow::Create(parent
, id
,
81 wxDefaultPosition
, wxDefaultSize
,
85 // The status bar should have a themed background
86 SetThemeEnabled( true );
91 SetFont(*wxSMALL_FONT
);
94 int height
= (int)((11*GetCharHeight())/10 + 2*GetBorderY());
95 SetSize(wxDefaultCoord
, wxDefaultCoord
, wxDefaultCoord
, height
);
102 wxSize
wxStatusBarGeneric::DoGetBestSize() const
106 // best width is the width of the parent
108 GetParent()->GetClientSize(&width
, NULL
);
110 width
= 80; // a dummy value
112 // best height is as calculated above in Create()
113 height
= (int)((11*GetCharHeight())/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?") );
122 // this will result in a call to SetStatusWidths() and thus an update to our
124 wxStatusBarBase::SetFieldsCount(number
, widths
);
127 void wxStatusBarGeneric::SetStatusText(const wxString
& text
, int number
)
129 wxCHECK_RET( (number
>= 0) && ((size_t)number
< m_panes
.GetCount()),
130 _T("invalid status bar field index") );
132 wxString oldText
= GetStatusText(number
);
135 wxStatusBarBase::SetStatusText(text
, number
);
138 GetFieldRect(number
, rect
);
140 Refresh(true, &rect
);
142 // it's common to show some text in the status bar before starting a
143 // relatively lengthy operation, ensure that the text is shown to the
144 // user immediately and not after the lengthy operation end
149 void wxStatusBarGeneric::SetStatusWidths(int n
, const int widths_field
[])
151 // only set status widths when n == number of statuswindows
152 wxCHECK_RET( (size_t)n
== m_panes
.GetCount(), _T("status bar field count mismatch") );
154 wxStatusBarBase::SetStatusWidths(n
, widths_field
);
158 GetClientSize(&width
, &m_lastClientHeight
);
159 m_widthsAbs
= CalculateAbsWidths(width
);
162 bool wxStatusBarGeneric::ShowsSizeGrip() const
164 if ( !HasFlag(wxST_SIZEGRIP
) )
167 wxTopLevelWindow
* const
168 tlw
= wxDynamicCast(wxGetTopLevelParent(GetParent()), wxTopLevelWindow
);
169 return tlw
&& !tlw
->IsMaximized() && tlw
->HasFlag(wxRESIZE_BORDER
);
172 void wxStatusBarGeneric::DrawFieldText(wxDC
& dc
, const wxRect
& rect
, int i
, int textHeight
)
174 wxString
text(GetStatusText(i
));
176 return; // optimization
178 int xpos
= rect
.x
+ wxFIELD_TEXT_MARGIN
,
179 maxWidth
= rect
.width
- 2*wxFIELD_TEXT_MARGIN
,
180 ypos
= (int) (((rect
.height
- textHeight
) / 2) + rect
.y
+ 0.5);
184 // don't write text over the size grip:
185 // NOTE: overloading DoGetClientSize() and GetClientAreaOrigin() wouldn't
186 // work because the adjustment needs to be done only when drawing
187 // the field text and not also when drawing the background, the
188 // size grip itself, etc
189 if ((GetLayoutDirection() == wxLayout_RightToLeft
&& i
== 0) ||
190 (GetLayoutDirection() != wxLayout_RightToLeft
&&
191 i
== (int)m_panes
.GetCount()-1))
193 const wxRect
& gripRc
= GetSizeGripRect();
195 // NOTE: we don't need any special treatment wrt to the layout direction
196 // since DrawText() will automatically adjust the origin of the
197 // text accordingly to the layout in use
199 maxWidth
-= gripRc
.width
;
203 // eventually ellipsize the text so that it fits the field width
204 text
= wxControl::Ellipsize(
206 GetLayoutDirection() == wxLayout_RightToLeft
? wxELLIPSIZE_START
: wxELLIPSIZE_END
,
208 wxELLIPSIZE_EXPAND_TAB
);
209 // Ellipsize() will do something only if necessary
211 #if defined( __WXGTK__ ) || defined(__WXMAC__)
217 dc
.DrawText(text
, xpos
, ypos
);
220 void wxStatusBarGeneric::DrawField(wxDC
& dc
, int i
, int textHeight
)
223 GetFieldRect(i
, rect
);
225 if (rect
.GetWidth() <= 0)
226 return; // happens when the status bar is shrinked in a very small area!
228 int style
= m_panes
[i
].nStyle
;
229 if (style
!= wxSB_FLAT
)
233 // Have grey background, plus 3-d border -
234 // One black rectangle.
235 // Inside this, left and top sides - dark grey. Bottom and right -
237 // Reverse it for wxSB_RAISED
239 dc
.SetPen((style
== wxSB_RAISED
) ? m_mediumShadowPen
: m_hilightPen
);
243 // Right and bottom lines
244 dc
.DrawLine(rect
.x
+ rect
.width
, rect
.y
,
245 rect
.x
+ rect
.width
, rect
.y
+ rect
.height
);
246 dc
.DrawLine(rect
.x
+ rect
.width
, rect
.y
+ rect
.height
,
247 rect
.x
, rect
.y
+ rect
.height
);
249 dc
.SetPen((style
== wxSB_RAISED
) ? m_hilightPen
: m_mediumShadowPen
);
251 // Left and top lines
252 dc
.DrawLine(rect
.x
, rect
.y
+ rect
.height
,
254 dc
.DrawLine(rect
.x
, rect
.y
,
255 rect
.x
+ rect
.width
, rect
.y
);
258 dc
.DrawLine(rect
.x
+ rect
.width
, rect
.height
+ 2,
259 rect
.x
, rect
.height
+ 2);
260 dc
.DrawLine(rect
.x
+ rect
.width
, rect
.y
,
261 rect
.x
+ rect
.width
, rect
.y
+ rect
.height
);
263 dc
.SetPen((style
== wxSB_RAISED
) ? m_hilightPen
: m_mediumShadowPen
);
264 dc
.DrawLine(rect
.x
, rect
.y
,
265 rect
.x
+ rect
.width
, rect
.y
);
266 dc
.DrawLine(rect
.x
, rect
.y
+ rect
.height
,
271 DrawFieldText(dc
, rect
, i
, textHeight
);
274 // Get the position and size of the field's internal bounding rectangle
275 bool wxStatusBarGeneric::GetFieldRect(int n
, wxRect
& rect
) const
277 wxCHECK_MSG( (n
>= 0) && ((size_t)n
< m_panes
.GetCount()), false,
278 _T("invalid status bar field index") );
280 if (m_widthsAbs
.IsEmpty())
284 for ( int i
= 0; i
< n
; i
++ )
285 rect
.x
+= m_widthsAbs
[i
];
289 rect
.width
= m_widthsAbs
[n
] - 2*m_borderX
;
290 rect
.height
= m_lastClientHeight
- 2*m_borderY
;
295 // Initialize colours
296 void wxStatusBarGeneric::InitColours()
298 #if defined(__WXPM__)
299 m_mediumShadowPen
= wxPen(wxColour(127, 127, 127));
300 m_hilightPen
= *wxWHITE_PEN
;
302 SetBackgroundColour(*wxLIGHT_GREY
);
303 SetForegroundColour(*wxBLACK
);
305 m_mediumShadowPen
= wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW
));
306 m_hilightPen
= wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DHILIGHT
));
307 #endif // __WXPM__/!__WXPM__
310 void wxStatusBarGeneric::SetMinHeight(int height
)
312 // check that this min height is not less than minimal height for the
313 // current font (min height is as calculated above in Create() except for border)
314 int minHeight
= (int)((11*GetCharHeight())/10);
316 if ( height
> minHeight
)
317 SetSize(wxDefaultCoord
, wxDefaultCoord
, wxDefaultCoord
, height
+ 2*m_borderY
);
320 wxRect
wxStatusBarGeneric::GetSizeGripRect() const
323 wxWindow::DoGetClientSize(&width
, &height
);
325 if (GetLayoutDirection() == wxLayout_RightToLeft
)
326 return wxRect(2, 2, height
-2, height
-4);
328 return wxRect(width
-height
-2, 2, height
-2, height
-4);
331 // ----------------------------------------------------------------------------
332 // wxStatusBarGeneric - event handlers
333 // ----------------------------------------------------------------------------
335 void wxStatusBarGeneric::OnPaint(wxPaintEvent
& WXUNUSED(event
) )
341 if ( ShowsSizeGrip() )
343 const wxRect
& rc
= GetSizeGripRect();
345 GetLayoutDirection() == wxLayout_RightToLeft
? GDK_WINDOW_EDGE_SOUTH_WEST
:
346 GDK_WINDOW_EDGE_SOUTH_EAST
;
347 gtk_paint_resize_grip( m_widget
->style
,
348 GTKGetDrawingWindow(),
349 (GtkStateType
) GTK_WIDGET_STATE (m_widget
),
354 rc
.x
, rc
.y
, rc
.width
, rc
.height
);
356 #endif // __WXGTK20__
358 if (GetFont().IsOk())
359 dc
.SetFont(GetFont());
361 // compute char height only once for all panes:
362 int textHeight
= dc
.GetCharHeight();
364 dc
.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT
);
365 for (size_t i
= 0; i
< m_panes
.GetCount(); i
++)
366 DrawField(dc
, i
, textHeight
);
369 // Responds to colour changes, and passes event on to children.
370 void wxStatusBarGeneric::OnSysColourChanged(wxSysColourChangedEvent
& event
)
374 // Propagate the event to the non-top-level children
375 wxWindow::OnSysColourChanged(event
);
378 void wxStatusBarGeneric::OnLeftDown(wxMouseEvent
& event
)
382 GetClientSize(&width
, &height
);
384 if ( ShowsSizeGrip() && (event
.GetX() > width
-height
) )
386 GtkWidget
*ancestor
= gtk_widget_get_toplevel( m_widget
);
388 if (!GTK_IS_WINDOW (ancestor
))
391 GdkWindow
*source
= GTKGetDrawingWindow();
395 gdk_window_get_origin( source
, &org_x
, &org_y
);
397 if (GetLayoutDirection() == wxLayout_RightToLeft
)
399 gtk_window_begin_resize_drag (GTK_WINDOW (ancestor
),
400 GDK_WINDOW_EDGE_SOUTH_WEST
,
402 org_x
- event
.GetX() + GetSize().x
,
403 org_y
+ event
.GetY(),
408 gtk_window_begin_resize_drag (GTK_WINDOW (ancestor
),
409 GDK_WINDOW_EDGE_SOUTH_EAST
,
411 org_x
+ event
.GetX(),
412 org_y
+ event
.GetY(),
425 void wxStatusBarGeneric::OnRightDown(wxMouseEvent
& event
)
429 GetClientSize(&width
, &height
);
431 if ( ShowsSizeGrip() && (event
.GetX() > width
-height
) )
433 GtkWidget
*ancestor
= gtk_widget_get_toplevel( m_widget
);
435 if (!GTK_IS_WINDOW (ancestor
))
438 GdkWindow
*source
= GTKGetDrawingWindow();
442 gdk_window_get_origin( source
, &org_x
, &org_y
);
444 gtk_window_begin_move_drag (GTK_WINDOW (ancestor
),
446 org_x
+ event
.GetX(),
447 org_y
+ event
.GetY(),
459 void wxStatusBarGeneric::OnSize(wxSizeEvent
& WXUNUSED(event
))
461 // FIXME: workarounds for OS/2 bugs have nothing to do here (VZ)
464 GetSize(&width
, &m_lastClientHeight
);
466 GetClientSize(&width
, &m_lastClientHeight
);
469 // recompute the cache of the field widths if the status bar width has changed
470 m_widthsAbs
= CalculateAbsWidths(width
);
473 #endif // wxUSE_STATUSBAR