// Set status line text
virtual void SetStatusText(const wxString& text, int number = 0);
- virtual wxString GetStatusText(int number = 0) const;
// Set status line widths
virtual void SetStatusWidths(int n, const int widths_field[]);
// common part of all ctors
void Init();
- // the array of the currently displayed strings
- wxArrayString m_statusStrings;
-
// the last known height of the client rect
int m_lastClientHeight;
#if wxUSE_NATIVE_STATUSBAR
+class WXDLLIMPEXP_CORE wxClientDC;
+
class WXDLLIMPEXP_CORE wxStatusBar : public wxStatusBarBase
{
public:
// each field of status line has it's own text
virtual void SetStatusText(const wxString& text, int number = 0);
- virtual wxString GetStatusText(int number = 0) const;
// set status line fields' widths
virtual void SetStatusWidths(int n, const int widths_field[]);
virtual int GetBorderX() const;
virtual int GetBorderY() const;
+ virtual bool SetFont(const wxFont& font);
+
virtual WXLRESULT MSWWindowProc(WXUINT nMsg,
WXWPARAM wParam,
WXLPARAM lParam);
protected:
void CopyFieldsWidth(const int widths[]);
void SetFieldsWidth();
+ void UpdateFieldText(int nField);
// override some base class virtuals
virtual wxSize DoGetBestSize() const;
virtual void DoMoveWindow(int x, int y, int width, int height);
+ // used by UpdateFieldText
+ wxClientDC *m_pDC;
+
private:
DECLARE_DYNAMIC_CLASS_NO_COPY(wxStatusBar)
};
long style = wxST_SIZEGRIP,
const wxString& name = wxStatusBarNameStr);
- virtual void DrawFieldText(wxDC& dc, int i);
- virtual void DrawField(wxDC& dc, int i);
+ virtual void DrawFieldText(wxDC& dc, const wxRect& rc, int i, int textHeight);
+ virtual void DrawField(wxDC& dc, int i, int textHeight);
+
virtual void SetStatusText(const wxString& text, int number = 0);
// Implementation
{
public:
wxStatusBarPane(int style = wxSB_NORMAL, size_t width = 0)
- : nStyle(style), nWidth(width) {}
+ : nStyle(style), nWidth(width) { arrStack.Add(wxEmptyString); }
int nStyle;
int nWidth; // the width maybe negative, indicating a variable-width field
// this is the array of the stacked strings of this pane; note that this
- // stack does not include the string currently displayed in this pane
- // as it's stored in the native status bar control
+ // stack does include also the string currently displayed in this pane
+ // as the version stored in the native status bar control is possibly
+ // ellipsized; note that arrStack.Last() is the top of the stack
+ // (i.e. the string shown in the status bar)
wxArrayString arrStack;
};
// field text
// ----------
- virtual void SetStatusText(const wxString& text, int number = 0) = 0;
- virtual wxString GetStatusText(int number = 0) const = 0;
+ virtual void SetStatusText(const wxString& text, int number = 0)
+ { m_panes[number].arrStack.Last() = text; }
+ virtual wxString GetStatusText(int number = 0) const
+ { return m_panes[number].arrStack.Last(); }
void PushStatusText(const wxString& text, int number = 0);
void PopStatusText(int number = 0);
// get/set the text of the given field
virtual void SetStatusText(const wxString& text, int number = 0);
- virtual wxString GetStatusText(int number = 0) const;
// Get the position and size of the field's internal bounding rectangle
virtual bool GetFieldRect(int i, wxRect& rect) const;
private:
// the current status fields strings
- wxArrayString m_statusText;
+ //wxArrayString m_statusText;
// the absolute status fields widths
wxArrayInt m_widthsAbs;
Sets the number of fields, and optionally the field widths.
@param number
- The number of fields.
+ The number of fields. If this is greater than the previous number,
+ then new fields with empty strings will be added to the status bar.
@param widths
An array of n integers interpreted in the same way as
in SetStatusWidths().
// save current status text in the stack
m_panes[number].arrStack.push_back(GetStatusText(number));
- // update current status text
SetStatusText(text, number);
+ // update current status text (eventually also in the native control)
}
void wxStatusBarBase::PopStatusText(int number)
{
+ wxASSERT_MSG(m_panes[number].arrStack.GetCount() == 1,
+ "can't pop any further string");
+
wxString text = m_panes[number].arrStack.back();
m_panes[number].arrStack.pop_back(); // also remove it from the stack
{
wxASSERT_MSG( number >= 0, _T("negative number of fields in wxStatusBar?") );
- // enlarge the m_statusStrings array if needed:
- for (size_t i = m_panes.GetCount(); i < (size_t)number; ++i)
- m_statusStrings.Add( wxEmptyString );
-
- // shrink the m_statusStrings array if needed:
- for (int j = (int)m_panes.GetCount() - 1; j >= number; --j)
- m_statusStrings.RemoveAt(j);
-
- // forget the old cached pixel widths
- m_widthsAbs.Empty();
-
+ // this will result in a call to SetStatusWidths() and thus an update to our
+ // m_widthsAbs cache
wxStatusBarBase::SetFieldsCount(number, widths);
-
- wxASSERT_MSG( m_panes.GetCount() == m_statusStrings.GetCount(),
- _T("This really should never happen, can we do away with m_panes.GetCount() here?") );
}
void wxStatusBarGeneric::SetStatusText(const wxString& text, int number)
wxCHECK_RET( (number >= 0) && ((size_t)number < m_panes.GetCount()),
_T("invalid status bar field index") );
- wxString oldText = m_statusStrings[number];
+ wxString oldText = GetStatusText(number);
if (oldText != text)
{
- m_statusStrings[number] = text;
+ wxStatusBarBase::SetStatusText(text, number);
wxRect rect;
GetFieldRect(number, rect);
}
}
-wxString wxStatusBarGeneric::GetStatusText(int n) const
-{
- wxCHECK_MSG( (n >= 0) && ((size_t)n < m_panes.GetCount()), wxEmptyString,
- _T("invalid status bar field index") );
-
- return m_statusStrings[n];
-}
-
void wxStatusBarGeneric::SetStatusWidths(int n, const int widths_field[])
{
// only set status widths when n == number of statuswindows
wxCHECK_RET( (size_t)n == m_panes.GetCount(), _T("status bar field count mismatch") );
- // forget the old cached pixel widths
- m_widthsAbs.Empty();
-
wxStatusBarBase::SetStatusWidths(n, widths_field);
+
+ // update cache
+ int width;
+ GetClientSize(&width, &m_lastClientHeight);
+ m_widthsAbs = CalculateAbsWidths(width);
}
bool wxStatusBarGeneric::ShowsSizeGrip() const
#include "wx/msw/uxtheme.h"
#endif
+// no idea for a default width, just choose something
+#define DEFAULT_FIELD_WIDTH 25
+
// ----------------------------------------------------------------------------
// macros
// ----------------------------------------------------------------------------
SetParent(NULL);
m_hWnd = 0;
m_windowId = 0;
+ m_pDC = NULL;
}
bool wxStatusBar::Create(wxWindow *parent,
// work correctly, we need to wait until we return to the main loop
PostSizeEventToParent();
+ // cache the DC instance used by UpdateFieldText
+ m_pDC = new wxClientDC(this);
+
return true;
}
PostSizeEventToParent();
}
+bool wxStatusBar::SetFont(const wxFont& font)
+{
+ if (!wxWindow::SetFont(font))
+ return false;
+
+ m_pDC->SetFont(font);
+ return true;
+}
+
void wxStatusBar::SetFieldsCount(int nFields, const int *widths)
{
// this is a Windows limitation
return;
}
+ wxStatusBarBase::SetStatusText(strText, nField);
+
+ UpdateFieldText(nField);
+}
+
+void wxStatusBar::UpdateFieldText(int nField)
+{
+ if (!m_pDC)
+ return;
+
// Get field style, if any
int style;
switch(m_panes[nField].nStyle)
break;
}
+ wxRect rc;
+ GetFieldRect(nField, rc);
+
+ int margin;
+ if (nField == GetFieldsCount()-1)
+ margin = -6; // windows reports a smaller rect for the last field; enlarge it
+ else
+ margin = 4;
+
+ // do we need to ellipsize this string?
+ wxString ellipsizedStr =
+ wxControl::Ellipsize(GetStatusText(nField), *m_pDC,
+ GetLayoutDirection() == wxLayout_RightToLeft ? wxELLIPSIZE_START : wxELLIPSIZE_END,
+ rc.GetWidth() - margin, // leave a small margin
+ wxELLIPSIZE_EXPAND_TAB);
+
// Pass both field number and style. MSDN library doesn't mention
// that nField and style have to be 'ORed'
- if ( !StatusBar_SetText(GetHwnd(), nField | style, strText.wx_str()) )
+ if ( !StatusBar_SetText(GetHwnd(), nField | style, ellipsizedStr.wx_str()) )
{
wxLogLastError(wxT("StatusBar_SetText"));
}
}
-wxString wxStatusBar::GetStatusText(int nField) const
-{
- wxCHECK_MSG( (nField >= 0) && ((size_t)nField < m_panes.GetCount()), wxEmptyString,
- _T("invalid statusbar field index") );
-
- wxString str;
- int len = StatusBar_GetTextLen(GetHwnd(), nField);
- if ( len > 0 )
- {
- StatusBar_GetText(GetHwnd(), nField, wxStringBuffer(str, len));
- }
-
- return str;
-}
-
int wxStatusBar::GetBorderX() const
{
int aBorders[3];
return true;
}
-// no idea for a default width, just choose something
-#define DEFAULT_FIELD_WIDTH 25
-
wxSize wxStatusBar::DoGetBestSize() const
{
int borders[3];
width = 2*DEFAULT_FIELD_WIDTH;
}
-
// calculate height
int height;
wxGetCharSize(GetHWND(), NULL, &height, GetFont());
}
#endif
+ if ( nMsg == WM_SIZE )
+ {
+ for (int i=0; i<GetFieldsCount(); i++)
+ UpdateFieldText(i);
+ // re-set the field text, in case we need to ellipsize
+ // (or de-ellipsize) some parts of it
+ }
+
return wxStatusBarBase::MSWWindowProc(nMsg, wParam, lParam);
}
#include "wx/osx/private.h"
+// Margin between the field text and the field rect
+#define wxFIELD_TEXT_MARGIN 2
+
BEGIN_EVENT_TABLE(wxStatusBarMac, wxStatusBarGeneric)
EVT_PAINT(wxStatusBarMac::OnPaint)
return true;
}
-void wxStatusBarMac::DrawFieldText(wxDC& dc, int i)
+void wxStatusBarMac::DrawFieldText(wxDC& dc, const wxRect& rect, int i, int textHeight)
{
int w, h;
GetSize( &w , &h );
- wxRect rect;
- GetFieldRect( i, rect );
if ( !MacIsReallyHilited() )
dc.SetTextForeground( wxColour( 0x80, 0x80, 0x80 ) );
wxString text(GetStatusText( i ));
- wxCoord x, y;
- dc.GetTextExtent(text, &x, &y);
+ /*wxCoord x, y;
+ dc.GetTextExtent(text, &x, &y); -- seems unused (FM)*/
- int leftMargin = 2;
- int xpos = rect.x + leftMargin + 1;
+ int xpos = rect.x + wxFIELD_TEXT_MARGIN + 1;
int ypos = 1;
if ( MacGetTopLevelWindow()->GetExtraStyle() & wxFRAME_EX_METAL )
ypos++;
dc.SetClippingRegion(rect.x, 0, rect.width, h);
-
dc.DrawText(text, xpos, ypos);
-
dc.DestroyClippingRegion();
}
-void wxStatusBarMac::DrawField(wxDC& dc, int i)
+void wxStatusBarMac::DrawField(wxDC& dc, int i, int textHeight)
{
- DrawFieldText(dc, i);
+ wxRect rect;
+ GetFieldRect(i, rect);
+
+ DrawFieldText(dc, rect, i, textHeight);
}
void wxStatusBarMac::SetStatusText(const wxString& text, int number)
{
+ // NOTE: seems this function is identic to wxStatusBarGeneric::SetStatusText;
+ // probably can be removed without problems (FM)
+
wxCHECK_RET( (number >= 0) && ((size_t)number < m_panes.GetCount()),
wxT("invalid status bar field index") );
- if ( m_statusStrings[number] == text )
- return ;
+ if ( GetStatusText(number) == text )
+ return;
+
+ wxStatusBarGeneric::SetStatusText(text, number);
- m_statusStrings[number] = text;
wxRect rect;
GetFieldRect(number, rect);
+
int w, h;
GetSize( &w, &h );
+
rect.y = 0;
rect.height = h ;
+
Refresh( true, &rect );
Update();
}
dc.DrawLine(0, 0, w, 0);
}
- if ( GetFont().Ok() )
+ if ( GetFont().IsOk() )
dc.SetFont(GetFont());
dc.SetBackgroundMode(wxTRANSPARENT);
+ // compute char height only once for all panes:
+ int textHeight = dc.GetCharHeight();
+
for ( size_t i = 0; i < m_panes.GetCount(); i ++ )
- DrawField(dc, i);
+ DrawField(dc, i, textHeight);
}
void wxStatusBarMac::MacHiliteChanged()
flags |= wxCONTROL_SIZEGRIP;
}
- m_renderer->DrawStatusField(dc, rect, m_statusText[n], flags, m_panes[n].nStyle);
+ m_renderer->DrawStatusField(dc, rect, GetStatusText(n), flags, m_panes[n].nStyle);
}
rect.x += rect.width + borderBetweenFields;
wxCHECK_RET( number >= 0 && (size_t)number < m_panes.GetCount(),
_T("invalid status bar field index in SetStatusText()") );
- if ( text == m_statusText[number] )
+ if ( text == GetStatusText(number) )
{
// nothing changed
return;
}
- m_statusText[number] = text;
+ wxStatusBarBase::SetStatusText(text, number);
RefreshField(number);
}
-wxString wxStatusBarUniv::GetStatusText(int number) const
-{
- wxCHECK_MSG( number >= 0 && (size_t)number < m_panes.GetCount(), wxEmptyString,
- _T("invalid status bar field index") );
-
- return m_statusText[number];
-}
// ----------------------------------------------------------------------------
// fields count/widths
void wxStatusBarUniv::SetFieldsCount(int number, const int *widths)
{
- m_statusText.SetCount(number);
wxStatusBarBase::SetFieldsCount(number, widths);
m_widthsAbs.Empty();