long style = wxSTB_DEFAULT_STYLE,
const wxString& name = wxStatusBarNameStr);
- // Create status line
- virtual void SetFieldsCount(int number = 1,
- const int *widths = (const int *) NULL);
-
- // Set status line text
- virtual void SetStatusText(const wxString& text, int number = 0);
-
- // Set status line widths
+ // implement base class methods
virtual void SetStatusWidths(int n, const int widths_field[]);
-
- // Get the position and size of the field's internal bounding rectangle
virtual bool GetFieldRect(int i, wxRect& rect) const;
-
- // sets the minimal vertical size of the status bar
virtual void SetMinHeight(int height);
virtual int GetBorderX() const { return m_borderX; }
int GetFieldFromPoint(const wxPoint& point) const;
-protected: // event handlers
+protected:
+ virtual void DoUpdateStatusText(int number);
+ // event handlers
void OnPaint(wxPaintEvent& event);
void OnSize(wxSizeEvent& event);
virtual ~wxStatusBar();
- // a status line can have several (<256) fields numbered from 0
+ // implement base class methods
virtual void SetFieldsCount(int number = 1, const int *widths = NULL);
-
- // each field of status line has it's own text
- virtual void SetStatusText(const wxString& text, int number = 0);
-
- // set status line fields' widths
virtual void SetStatusWidths(int n, const int widths_field[]);
-
- // set status line fields' styles
virtual void SetStatusStyles(int n, const int styles[]);
-
- // sets the minimal vertical size of the status bar
virtual void SetMinHeight(int height);
-
- // get the position and size of the field's internal bounding rectangle
virtual bool GetFieldRect(int i, wxRect& rect) const;
- // get the border size
virtual int GetBorderX() const;
virtual int GetBorderY() const;
+ // override some wxWindow virtual methods too
virtual bool SetFont(const wxFont& font);
virtual WXLRESULT MSWWindowProc(WXUINT nMsg,
WXLPARAM lParam);
protected:
- void CopyFieldsWidth(const int widths[]);
- void SetFieldsWidth();
- void UpdateFieldText(int nField);
+ // implement base class pure virtual method
+ virtual void DoUpdateStatusText(int number);
// override some base class virtuals
virtual wxSize DoGetBestSize() const;
virtual bool MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM* result);
#endif
- // used by UpdateFieldText
+ // implementation of the public SetStatusWidths()
+ void MSWUpdateFieldsWidths();
+
+ // used by DoUpdateStatusText()
wxClientDC *m_pDC;
// the tooltips used when wxSTB_SHOW_TIPS is given
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
virtual void MacHiliteChanged();
void OnPaint(wxPaintEvent& event);
protected:
+ virtual void DoUpdateStatusText(int number = 0);
+
DECLARE_EVENT_TABLE()
};
// a status line can have several (<256) fields numbered from 0
virtual void SetFieldsCount(int number = 1, const int *widths = NULL);
- // 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
+ // implement base class methods
virtual void SetStatusWidths(int n, const int widths_field[]);
-
- // sets the minimal vertical size of the status bar
virtual void SetMinHeight(int height);
-
- // get the position and size of the field's internal bounding rectangle
virtual bool GetFieldRect(int i, wxRect& rect) const;
- // get the border size
virtual int GetBorderX() const;
virtual int GetBorderY() const;
void DrawStatusBar();
protected:
+ virtual void DoUpdateStatusText(int nField);
+
void CopyFieldsWidth(const int widths[]);
void SetFieldsWidth();
/*
class WXDLLIMPEXP_CORE wxStatusBarPane
{
- // only wxStatusBarBase can access our internal members and modify them:
- friend class WXDLLIMPEXP_FWD_CORE wxStatusBarBase;
-
public:
wxStatusBarPane(int style = wxSB_NORMAL, size_t width = 0)
: m_nStyle(style), m_nWidth(width)
- { m_arrStack.Add(wxEmptyString); m_bEllipsized=false; }
+ { m_bEllipsized = false; }
+
+ int GetWidth() const { return m_nWidth; }
+ int GetStyle() const { return m_nStyle; }
+ wxString GetText() const { return m_text; }
- int GetWidth() const
- { return m_nWidth; }
- int GetStyle() const
- { return m_nStyle; }
- const wxArrayString& GetStack() const
- { return m_arrStack; }
+ // implementation-only from now on
+ // -------------------------------
- // implementation-only getter:
bool IsEllipsized() const
{ return m_bEllipsized; }
+ void SetIsEllipsized(bool isEllipsized) { m_bEllipsized = isEllipsized; }
- // NOTE: there are no setters in wxStatusBarPane;
- // use wxStatusBar functions to modify a wxStatusBarPane
+ void SetWidth(int width) { m_nWidth = width; }
+ void SetStyle(int style) { m_nStyle = style; }
-protected:
+ // set text, return true if it changed or false if it was already set to
+ // this value
+ bool SetText(const wxString& text);
+
+ // save the existing text on top of our stack and make the new text
+ // current; return true if the text really changed
+ bool PushText(const wxString& text);
+
+ // restore the message saved by the last call to Push() (unless it was
+ // changed by an intervening call to SetText()) and return true if we
+ // really restored anything
+ bool PopText();
+
+private:
int m_nStyle;
- int m_nWidth; // the width maybe negative, indicating a variable-width field
+ int m_nWidth; // may be negative, indicating a variable-width field
+ wxString m_text;
- // this is the array of the stacked strings of this pane; note that this
- // 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 m_arrStack.Last() is the top of the stack
- // (i.e. the string shown in the status bar)
+ // the array used to keep the previous values of this pane after a
+ // PushStatusText() call, its top element is the value to restore after the
+ // next PopStatusText() call while the currently shown value is always in
+ // m_text
wxArrayString m_arrStack;
- // was the m_arrStack.Last() string shown in the status bar control ellipsized?
+ // is the currently shown value shown with ellipsis in the status bar?
bool m_bEllipsized;
};
// field text
// ----------
- // NOTE: even if it is not pure virtual, SetStatusText() must be overloaded by
- // the derived classes to update the given text in the native control
- virtual void SetStatusText(const wxString& text, int number = 0)
- { m_panes[number].GetStack().Last() = text; }
- virtual wxString GetStatusText(int number = 0) const
- { return m_panes[number].GetStack().Last(); }
- const wxArrayString& GetStatusStack(int n) const
- { return m_panes[n].GetStack(); }
+ // just change or get the currently shown text
+ void SetStatusText(const wxString& text, int number = 0);
+ wxString GetStatusText(int number = 0) const;
+ // change the currently shown text to the new one and save the current
+ // value to be restored by the next call to PopStatusText()
void PushStatusText(const wxString& text, int number = 0);
void PopStatusText(int number = 0);
virtual bool CanBeOutsideClientArea() const { return true; }
protected:
+ // called after the status bar pane text changed and should update its
+ // display
+ virtual void DoUpdateStatusText(int number) = 0;
+
// wxWindow overrides:
"Do not set tooltip(s) manually when using wxSTB_SHOW_TIPS!");
wxWindow::DoSetToolTip(tip);
}
-#endif
-
+#endif // wxUSE_TOOLTIPS
virtual wxBorder GetDefaultBorder() const { return wxBORDER_NONE; }
// calculate the real field widths for the given total available size
wxArrayInt CalculateAbsWidths(wxCoord widthTotal) const;
- // an internal utility used to keep track of which panes have labels
- // which were last rendered as ellipsized...
- void SetEllipsizedFlag(int n, bool ellipsized)
- { m_panes[n].m_bEllipsized = ellipsized; }
+ // should be called to remember if the pane text is currently being show
+ // ellipsized or not
+ void SetEllipsizedFlag(int n, bool isEllipsized);
+
// the array with the pane infos:
wxStatusBarPaneArray m_panes;
long style = wxSTB_DEFAULT_STYLE,
const wxString& name = wxPanelNameStr);
- // set field count/widths
+ // implement base class methods
virtual void SetFieldsCount(int number = 1, const int *widths = NULL);
virtual void SetStatusWidths(int n, const int widths[]);
- // get/set the text of the given field
- virtual void SetStatusText(const wxString& text, int number = 0);
-
- // Get the position and size of the field's internal bounding rectangle
virtual bool GetFieldRect(int i, wxRect& rect) const;
-
- // sets the minimal vertical size of the status bar
virtual void SetMinHeight(int height);
- // get the dimensions of the horizontal and vertical borders
virtual int GetBorderX() const;
virtual int GetBorderY() const;
{ return const_cast<wxStatusBar*>(this); }
protected:
+ virtual void DoUpdateStatusText(int i);
+
// recalculate the field widths
void OnSize(wxSizeEvent& event);
// get the rect for this field without ani side effects (see code)
wxRect DoGetFieldRect(int n) const;
- // refresh the given field
- void RefreshField(int i);
-
// common part of all ctors
void Init();
int GetStyle() const;
/**
- Returns the stack of strings pushed on this pane.
-
- Note that this stack does include also the string currently displayed in this pane
- as the version stored in the native status bar control is possibly ellipsized.
-
- Also note that GetStack().Last() is the top of the stack (i.e. the string shown
- in the status bar).
- */
- const wxArrayString& GetStack() const;
+ Returns the text currently shown in this pane.
+ */
+ wxString GetText() const;
};
/**
*/
virtual wxString GetStatusText(int i = 0) const;
- /**
- Returns the stack of strings pushed (see PushStatusText()) on the
- @a n-th field.
-
- See wxStatusBarPane::GetStack() for more info.
- */
- const wxArrayString& GetStatusStack(int n) const;
-
/**
Returns the width of the @a n-th field.
int GetStatusStyle(int n) const;
/**
- Sets the field text to the top of the stack, and pops the stack of saved
- strings.
+ Restores the text to the value it had before the last call to
+ PushStatusText().
+
+ Notice that if SetStatusText() had been called in the meanwhile,
+ PopStatusText() will not change the text, i.e. it does not override
+ explicit changes to status text but only restores the saved text if it
+ hadn't been changed since.
@see PushStatusText()
*/
void PopStatusText(int field = 0);
/**
- Saves the current field text in a per-field stack, and sets the field text
- to the string passed as argument.
+ Saves the current field text in a per-field stack, and sets the field
+ text to the string passed as argument.
@see PopStatusText()
*/
/**
Sets the status text for the @a i-th field.
- The given text will replace the current text. Note that unlike PushStatusText()
- this function won't save the current text (and calling PopStatusText() won't
- restore it!).
+ The given text will replace the current text.
+
+ Note that if PushStatusText() had been called before the new text will
+ also replace the last saved value to make sure that the next call to
+ PopStatusText() doesn't restore the old value, which was overwritten by
+ the call to this function.
@param text
The text to be set. Use an empty string ("") to clear the field.
const char wxStatusBarNameStr[] = "statusBar";
+// ============================================================================
+// wxStatusBarPane implementation
+// ============================================================================
+
+bool wxStatusBarPane::SetText(const wxString& text)
+{
+ if ( text == m_text )
+ return false;
+
+ /*
+ If we have a message to restore on the stack, we update it to
+ correspond to the current one so that a sequence of calls such as
+
+ 1. SetStatusText("foo")
+ 2. PushStatusText("bar")
+ 3. SetStatusText("new foo")
+ 4. PopStatusText()
+
+ doesn't overwrite the "new foo" which should be shown at the end with
+ the old value "foo". This would be unexpected and hard to avoid,
+ especially when PushStatusText() is used internally by wxWidgets
+ without knowledge of the user program, as it is for showing the menu
+ and toolbar help strings.
+
+ By updating the top of the stack we ensure that the next call to
+ PopStatusText() basically becomes a NOP without breaking the balance
+ between the calls to push and pop as we would have done if we really
+ called PopStatusText() here.
+ */
+ if ( !m_arrStack.empty() )
+ {
+ m_arrStack.back() = text;
+ }
+
+ m_text = text;
+
+ return true;
+}
+
+bool wxStatusBarPane::PushText(const wxString& text)
+{
+ // save the currently shown text
+ m_arrStack.push_back(m_text);
+
+ // and update the new one if necessary
+ if ( text == m_text )
+ return false;
+
+ m_text = text;
+
+ return true;
+}
+
+bool wxStatusBarPane::PopText()
+{
+ wxCHECK_MSG( !m_arrStack.empty(), false, "no status message to pop" );
+
+ const wxString text = m_arrStack.back();
+
+ m_arrStack.pop_back();
+
+ if ( text == m_text )
+ return false;
+
+ m_text = text;
+
+ return true;
+}
// ============================================================================
// wxStatusBarBase implementation
else
{
for ( size_t i = 0; i < m_panes.GetCount(); i++ )
- m_panes[i].m_nWidth = widths[i];
+ m_panes[i].SetWidth(widths[i]);
m_bSameWidthForAllPanes = false;
}
wxASSERT_MSG( (size_t)n == m_panes.GetCount(), wxT("field number mismatch") );
for ( size_t i = 0; i < m_panes.GetCount(); i++ )
- m_panes[i].m_nStyle = styles[i];
+ m_panes[i].SetStyle(styles[i]);
// update the display after the widths changed
Refresh();
}
// ----------------------------------------------------------------------------
-// status text stacks
+// setting/getting status text
+// ----------------------------------------------------------------------------
+
+void wxStatusBarBase::SetStatusText(const wxString& text, int number)
+{
+ wxCHECK_RET( (unsigned)number < m_panes.size(),
+ "invalid status bar field index" );
+
+ if ( m_panes[number].SetText(text) )
+ DoUpdateStatusText(number);
+}
+
+wxString wxStatusBarBase::GetStatusText(int number) const
+{
+ wxCHECK_MSG( (unsigned)number < m_panes.size(), wxString(),
+ "invalid status bar field index" );
+
+ return m_panes[number].GetText();
+}
+
+void wxStatusBarBase::SetEllipsizedFlag(int number, bool isEllipsized)
+{
+ wxCHECK_RET( (unsigned)number < m_panes.size(),
+ "invalid status bar field index" );
+
+ m_panes[number].SetIsEllipsized(isEllipsized);
+}
+
+// ----------------------------------------------------------------------------
+// pushing/popping status text
// ----------------------------------------------------------------------------
void wxStatusBarBase::PushStatusText(const wxString& text, int number)
{
- // save the new text (in non-ellipsized form) in the stack
- m_panes[number].m_arrStack.push_back(text);
-
- SetStatusText(text, number);
- // update current status text (which will possibly be ellipsized)
- // also in the native control
-
- // SetStatusText() typically has an optimization built-in to avoid flickering
- // which won't refresh the status bar pane if the current top of the stack
- // is identic to the text passed to that function.
- // Since this optimization however cannot detect push/pop operations on the stack
- // we need to explicitely refresh the status bar pane ourselves:
- wxRect rect;
- GetFieldRect(number, rect);
- Refresh(true, &rect);
- Update();
+ wxCHECK_RET( (unsigned)number < m_panes.size(),
+ "invalid status bar field index" );
+
+ if ( m_panes[number].PushText(text) )
+ DoUpdateStatusText(number);
}
void wxStatusBarBase::PopStatusText(int number)
{
- wxASSERT_MSG(m_panes[number].m_arrStack.GetCount() > 1,
- "can't pop any further string");
-
- // the top of the stack is the status text currently shown in the native control;
- // remove it
- m_panes[number].m_arrStack.pop_back();
-
- // restore the previous status text in the native control
- const wxString& text = m_panes[number].m_arrStack.back();
- SetStatusText(text, number);
-
- // see comment in wxStatusBarBase::PushStatusText about why we need to explicitely
- // refresh the status bar pane
- wxRect rect;
- GetFieldRect(number, rect);
- Refresh(true, &rect);
- Update();
+ wxCHECK_RET( (unsigned)number < m_panes.size(),
+ "invalid status bar field index" );
+
+ if ( m_panes[number].PopText() )
+ DoUpdateStatusText(number);
}
#endif // wxUSE_STATUSBAR
return wxSize(width, height);
}
-void wxStatusBarGeneric::SetFieldsCount(int number, const int *widths)
+void wxStatusBarGeneric::DoUpdateStatusText(int number)
{
- wxASSERT_MSG( number >= 0, wxT("negative number of fields in wxStatusBar?") );
-
- // this will result in a call to SetStatusWidths() and thus an update to our
- // m_widthsAbs cache
- wxStatusBarBase::SetFieldsCount(number, widths);
-}
-
-void wxStatusBarGeneric::SetStatusText(const wxString& text, int number)
-{
- wxCHECK_RET( (number >= 0) && ((size_t)number < m_panes.GetCount()),
- wxT("invalid status bar field index") );
-
- wxString oldText = GetStatusText(number);
- if (oldText != text)
- {
- wxStatusBarBase::SetStatusText(text, number);
-
- wxRect rect;
- GetFieldRect(number, rect);
+ wxRect rect;
+ GetFieldRect(number, rect);
- Refresh(true, &rect);
+ Refresh(true, &rect);
- // it's common to show some text in the status bar before starting a
- // relatively lengthy operation, ensure that the text is shown to the
- // user immediately and not after the lengthy operation end
- Update();
- }
+ // it's common to show some text in the status bar before starting a
+ // relatively lengthy operation, ensure that the text is shown to the
+ // user immediately and not after the lengthy operation end
+ Update();
}
void wxStatusBarGeneric::SetStatusWidths(int n, const int widths_field[])
SetFieldsCount(1);
SubclassWin(m_hWnd);
- // cache the DC instance used by UpdateFieldText:
+ // cache the DC instance used by DoUpdateStatusText:
// NOTE: create the DC before calling InheritAttributes() since
// it may result in a call to our SetFont()
m_pDC = new wxClientDC(this);
wxStatusBarBase::SetFieldsCount(nFields, widths);
- SetFieldsWidth();
+ MSWUpdateFieldsWidths();
// keep in synch also our m_tooltips array
{
wxStatusBarBase::SetStatusWidths(n, widths);
- SetFieldsWidth();
+ MSWUpdateFieldsWidths();
}
-void wxStatusBar::SetFieldsWidth()
+void wxStatusBar::MSWUpdateFieldsWidths()
{
if ( m_panes.IsEmpty() )
return;
delete [] pWidths;
- // FIXME: we may want to call UpdateFieldText() here since we may need to (de)ellipsize status texts
+ // FIXME: we may want to call DoUpdateStatusText() here since we may need to (de)ellipsize status texts
}
-void wxStatusBar::SetStatusText(const wxString& strText, int nField)
-{
- wxCHECK_RET( (nField >= 0) && ((size_t)nField < m_panes.GetCount()),
- "invalid statusbar field index" );
-
- if ( strText == GetStatusText(nField) )
- {
- // don't call StatusBar_SetText() to avoid flicker
- return;
- }
-
- wxStatusBarBase::SetStatusText(strText, nField);
-
- UpdateFieldText(nField);
-}
-
-void wxStatusBar::UpdateFieldText(int nField)
+void wxStatusBar::DoUpdateStatusText(int nField)
{
if (!m_pDC)
return;
}
// adjust fields widths to the new size
- SetFieldsWidth();
+ MSWUpdateFieldsWidths();
// we have to trigger wxSizeEvent if there are children window in status
// bar because GetFieldRect returned incorrect (not updated) values up to
if ( nMsg == WM_SIZE && needsEllipsization )
{
for (int i=0; i<GetFieldsCount(); i++)
- UpdateFieldText(i);
+ DoUpdateStatusText(i);
// re-set the field text, in case we need to ellipsize
// (or de-ellipsize) some parts of it
}
DrawFieldText(dc, rect, i, textHeight);
}
-void wxStatusBarMac::SetStatusText(const wxString& text, int number)
+void wxStatusBarMac::DoUpdateStatusText(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 ( GetStatusText(number) == text )
- return;
-
- wxStatusBarGeneric::SetStatusText(text, number);
-
wxRect rect;
GetFieldRect(number, rect);
DeleteStatusBuffer();
}
-void wxStatusBarPalm::SetStatusText(const wxString& strText, int nField)
+void wxStatusBarPalm::DoUpdateStatusText(int nField)
{
- wxCHECK_RET( (nField >= 0) && (nField < m_nFields),
- wxT("invalid statusbar field index") );
-
SetStatusBufferText(strText,nField);
DrawStatusBar();
}
-wxString wxStatusBarPalm::GetStatusText(int nField) const
-{
- wxCHECK_MSG( (nField >= 0) && (nField < m_nFields), wxEmptyString,
- wxT("invalid statusbar field index") );
-
- wxString text;
- return text;
-}
-
void wxStatusBarPalm::DrawStatusBar()
{
#if 0
}
}
-void wxStatusBarUniv::RefreshField(int i)
+void wxStatusBarUniv::DoUpdateStatusText(int i)
{
wxRect rect;
if ( GetFieldRect(i, rect) )
}
}
-// ----------------------------------------------------------------------------
-// fields text
-// ----------------------------------------------------------------------------
-
-void wxStatusBarUniv::SetStatusText(const wxString& text, int number)
-{
- wxCHECK_RET( number >= 0 && (size_t)number < m_panes.GetCount(),
- wxT("invalid status bar field index in SetStatusText()") );
-
- if ( text == GetStatusText(number) )
- {
- // nothing changed
- return;
- }
-
- wxStatusBarBase::SetStatusText(text, number);
-
- RefreshField(number);
-}
-
-
// ----------------------------------------------------------------------------
// fields count/widths
// ----------------------------------------------------------------------------