diff --git a/include/wx/control.h b/include/wx/control.h index 86563645e0..0e646b2faa 100644 --- a/include/wx/control.h +++ b/include/wx/control.h @@ -178,11 +178,6 @@ protected: // initialize the common fields of wxCommandEvent void InitCommandEvent(wxCommandEvent& event) const; - // Ellipsize() helper: - static wxString DoEllipsizeSingleLine(const wxString& label, const wxDC& dc, - wxEllipsizeMode mode, int maxWidth, - int replacementWidth); - #if wxUSE_MARKUP // Remove markup from the given string, returns empty string on error i.e. // if markup was syntactically invalid. diff --git a/include/wx/generic/stattextg.h b/include/wx/generic/stattextg.h index 2a85d99c17..84210423d4 100644 --- a/include/wx/generic/stattextg.h +++ b/include/wx/generic/stattextg.h @@ -54,8 +54,8 @@ public: protected: virtual wxSize DoGetBestClientSize() const wxOVERRIDE; - virtual wxString DoGetLabel() const wxOVERRIDE { return m_label; } - virtual void DoSetLabel(const wxString& label) wxOVERRIDE; + virtual wxString WXGetVisibleLabel() const wxOVERRIDE { return m_label; } + virtual void WXSetVisibleLabel(const wxString& label) wxOVERRIDE; void DoSetSize(int x, int y, int width, int height, int sizeFlags) wxOVERRIDE; diff --git a/include/wx/gtk/stattext.h b/include/wx/gtk/stattext.h index b94f399a50..37f2939c47 100644 --- a/include/wx/gtk/stattext.h +++ b/include/wx/gtk/stattext.h @@ -49,8 +49,8 @@ protected: virtual wxSize DoGetBestSize() const wxOVERRIDE; - virtual wxString DoGetLabel() const wxOVERRIDE; - virtual void DoSetLabel(const wxString& str) wxOVERRIDE; + virtual wxString WXGetVisibleLabel() const wxOVERRIDE; + virtual void WXSetVisibleLabel(const wxString& str) wxOVERRIDE; #if wxUSE_MARKUP virtual bool DoSetLabelMarkup(const wxString& markup) wxOVERRIDE; #endif // wxUSE_MARKUP diff --git a/include/wx/motif/stattext.h b/include/wx/motif/stattext.h index e92780cd02..2e6ce08699 100644 --- a/include/wx/motif/stattext.h +++ b/include/wx/motif/stattext.h @@ -51,8 +51,8 @@ public: virtual WXWidget GetLabelWidget() const { return m_labelWidget; } - virtual void DoSetLabel(const wxString& str); - virtual wxString DoGetLabel() const; + virtual void WXSetVisibleLabel(const wxString& str); + virtual wxString WXGetVisibleLabel() const; virtual wxSize DoGetBestSize() const; protected: diff --git a/include/wx/msw/stattext.h b/include/wx/msw/stattext.h index e52248fc84..9c9f0fb227 100644 --- a/include/wx/msw/stattext.h +++ b/include/wx/msw/stattext.h @@ -47,8 +47,8 @@ protected: int sizeFlags = wxSIZE_AUTO) wxOVERRIDE; virtual wxSize DoGetBestClientSize() const wxOVERRIDE; - virtual wxString DoGetLabel() const wxOVERRIDE; - virtual void DoSetLabel(const wxString& str) wxOVERRIDE; + virtual wxString WXGetVisibleLabel() const wxOVERRIDE; + virtual void WXSetVisibleLabel(const wxString& str) wxOVERRIDE; wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxStaticText); }; diff --git a/include/wx/osx/stattext.h b/include/wx/osx/stattext.h index 45249da560..87136c1861 100644 --- a/include/wx/osx/stattext.h +++ b/include/wx/osx/stattext.h @@ -41,8 +41,8 @@ public: protected : - virtual wxString DoGetLabel() const wxOVERRIDE; - virtual void DoSetLabel(const wxString& str) wxOVERRIDE; + virtual wxString WXGetVisibleLabel() const wxOVERRIDE; + virtual void WXSetVisibleLabel(const wxString& str) wxOVERRIDE; virtual wxSize DoGetBestSize() const wxOVERRIDE; diff --git a/include/wx/qt/stattext.h b/include/wx/qt/stattext.h index f427f16490..5a19698191 100644 --- a/include/wx/qt/stattext.h +++ b/include/wx/qt/stattext.h @@ -31,10 +31,13 @@ public: const wxString &name = wxStaticTextNameStr ); virtual void SetLabel(const wxString& label) wxOVERRIDE; - virtual wxString GetLabel() const wxOVERRIDE; virtual QWidget *GetHandle() const wxOVERRIDE; +protected: + virtual wxString WXGetVisibleLabel() const wxOVERRIDE; + virtual void WXSetVisibleLabel(const wxString& str) wxOVERRIDE; + private: QLabel *m_qtLabel; diff --git a/include/wx/stattext.h b/include/wx/stattext.h index 237f93620e..369ab6dc87 100644 --- a/include/wx/stattext.h +++ b/include/wx/stattext.h @@ -63,21 +63,27 @@ protected: // functions required for wxST_ELLIPSIZE_* support // style. Shouldn't be called if we don't have any. wxString Ellipsize(const wxString& label) const; - // to be called when updating the size of the static text: - // updates the label redoing ellipsization calculations + + // Note that even though ports with native support for ellipsization + // (currently only wxGTK) don't need this stuff, we still need to define it + // as it's used by wxGenericStaticText. + + // Must be called when the size or font changes to redo the ellipsization + // for the new size. Calls WXSetVisibleLabel() to actually update the + // display. void UpdateLabel(); - // These functions are platform-specific and must be overridden in ports - // which do not natively support ellipsization and they must be implemented - // in a way so that the m_labelOrig member of wxControl is not touched: + // These functions are platform-specific and must be implemented in the + // platform-specific code. They must not use or update m_labelOrig. - // returns the real label currently displayed inside the control. - virtual wxString DoGetLabel() const { return wxEmptyString; } + // Returns the label currently displayed inside the control, with mnemonics + // if any. + virtual wxString WXGetVisibleLabel() const = 0; - // sets the real label currently displayed inside the control, - // _without_ invalidating the size. The text passed is always markup-free - // but may contain the mnemonic characters. - virtual void DoSetLabel(const wxString& WXUNUSED(str)) { } + // Sets the real label currently displayed inside the control, _without_ + // invalidating the size. The text passed is always markup-free but may + // contain the mnemonic characters. + virtual void WXSetVisibleLabel(const wxString& str) = 0; // Update the current size to match the best size unless wxST_NO_AUTORESIZE // style is explicitly used. diff --git a/include/wx/univ/stattext.h b/include/wx/univ/stattext.h index 891ad7cf60..54a0284c58 100644 --- a/include/wx/univ/stattext.h +++ b/include/wx/univ/stattext.h @@ -58,8 +58,8 @@ protected: // draw the control virtual void DoDraw(wxControlRenderer *renderer) wxOVERRIDE; - virtual void DoSetLabel(const wxString& str) wxOVERRIDE; - virtual wxString DoGetLabel() const wxOVERRIDE; + virtual void WXSetVisibleLabel(const wxString& str) wxOVERRIDE; + virtual wxString WXGetVisibleLabel() const wxOVERRIDE; wxDECLARE_DYNAMIC_CLASS(wxStaticText); }; diff --git a/samples/widgets/static.cpp b/samples/widgets/static.cpp index 163d500cda..73821d9666 100644 --- a/samples/widgets/static.cpp +++ b/samples/widgets/static.cpp @@ -49,15 +49,6 @@ // constants // ---------------------------------------------------------------------------- -// control ids -enum -{ - StaticPage_Reset = wxID_HIGHEST, - StaticPage_BoxText, - StaticPage_LabelText, - StaticPage_LabelTextWithMarkup -}; - // alignment radiobox values enum { @@ -114,7 +105,7 @@ public: protected: // event handlers - void OnCheckOrRadioBox(wxCommandEvent& event); + void OnCheckEllipsize(wxCommandEvent& event); #ifdef wxHAS_WINDOW_LABEL_IN_STATIC_BOX void OnBoxCheckBox(wxCommandEvent& event); #endif // wxHAS_WINDOW_LABEL_IN_STATIC_BOX @@ -176,26 +167,9 @@ protected: #endif // wxUSE_MARKUP private: - wxDECLARE_EVENT_TABLE(); DECLARE_WIDGETS_PAGE(StaticWidgetsPage) }; -// ---------------------------------------------------------------------------- -// event tables -// ---------------------------------------------------------------------------- - -wxBEGIN_EVENT_TABLE(StaticWidgetsPage, WidgetsPage) - EVT_BUTTON(StaticPage_Reset, StaticWidgetsPage::OnButtonReset) - EVT_BUTTON(StaticPage_LabelText, StaticWidgetsPage::OnButtonLabelText) -#if wxUSE_MARKUP - EVT_BUTTON(StaticPage_LabelTextWithMarkup, StaticWidgetsPage::OnButtonLabelWithMarkupText) -#endif // wxUSE_MARKUP - EVT_BUTTON(StaticPage_BoxText, StaticWidgetsPage::OnButtonBoxText) - - EVT_CHECKBOX(wxID_ANY, StaticWidgetsPage::OnCheckOrRadioBox) - EVT_RADIOBOX(wxID_ANY, StaticWidgetsPage::OnCheckOrRadioBox) -wxEND_EVENT_TABLE() - // ============================================================================ // implementation // ============================================================================ @@ -286,6 +260,8 @@ void StaticWidgetsPage::CreateContent() sizerLeft->Add(5, 5, 0, wxGROW | wxALL, 5); // spacer m_chkEllipsize = CreateCheckBoxAndAddToSizer(sizerLeft, "&Ellipsize"); + m_chkEllipsize->Bind(wxEVT_CHECKBOX, + &StaticWidgetsPage::OnCheckEllipsize, this); static const wxString ellipsizeMode[] = { @@ -301,8 +277,9 @@ void StaticWidgetsPage::CreateContent() sizerLeft->Add(m_radioEllipsize, 0, wxGROW | wxALL, 5); - wxButton *btn = new wxButton(this, StaticPage_Reset, "&Reset"); - sizerLeft->Add(btn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 15); + wxButton *b0 = new wxButton(this, wxID_ANY, "&Reset"); + b0->Bind(wxEVT_BUTTON, &StaticWidgetsPage::OnButtonReset, this); + sizerLeft->Add(b0, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 15); // middle pane wxSizer *sizerMiddle = new wxStaticBoxSizer(wxVERTICAL, this, @@ -346,8 +323,8 @@ void StaticWidgetsPage::CreateContent() #if wxUSE_MARKUP m_textLabelWithMarkup->SetValue("Another label, this time decorated " "with markup; here you need entities " - "for the symbols: < > & ' " " - " but you can still place &mnemonics..."); + "for the symbols: < > && ' " " + " but you can still use &mnemonics too"); #endif // wxUSE_MARKUP // right pane @@ -573,12 +550,9 @@ void StaticWidgetsPage::OnButtonReset(wxCommandEvent& WXUNUSED(event)) CreateStatic(); } -void StaticWidgetsPage::OnCheckOrRadioBox(wxCommandEvent& event) +void StaticWidgetsPage::OnCheckEllipsize(wxCommandEvent& event) { - if (event.GetEventObject() == static_cast(m_chkEllipsize)) - { - m_radioEllipsize->Enable(event.IsChecked()); - } + m_radioEllipsize->Enable(event.IsChecked()); CreateStatic(); } diff --git a/src/common/ctrlcmn.cpp b/src/common/ctrlcmn.cpp index cb1c0fcf41..8aabe0bfa7 100644 --- a/src/common/ctrlcmn.cpp +++ b/src/common/ctrlcmn.cpp @@ -194,20 +194,24 @@ int wxControlBase::FindAccelIndex(const wxString& label, wxString *labelOnly) labelOnly->Alloc(label.length()); } + // When computing the offset below, we need to ignore the characters that + // are not actually displayed, i.e. the ampersands themselves. + int numSkipped = 0; int indexAccel = -1; for ( wxString::const_iterator pc = label.begin(); pc != label.end(); ++pc ) { if ( *pc == MNEMONIC_PREFIX ) { ++pc; // skip it + ++numSkipped; + if ( pc == label.end() ) break; else if ( *pc != MNEMONIC_PREFIX ) { if ( indexAccel == -1 ) { - // remember it (-1 is for MNEMONIC_PREFIX itself - indexAccel = pc - label.begin() - 1; + indexAccel = pc - label.begin() - numSkipped; } else { @@ -278,7 +282,8 @@ namespace struct EllipsizeCalculator { EllipsizeCalculator(const wxString& s, const wxDC& dc, - int maxFinalWidthPx, int replacementWidthPx) + int maxFinalWidthPx, int replacementWidthPx, + int flags) : m_initialCharToRemove(0), m_nCharsToRemove(0), @@ -290,6 +295,31 @@ struct EllipsizeCalculator { m_isOk = dc.GetPartialTextExtents(s, m_charOffsetsPx); wxASSERT( m_charOffsetsPx.GetCount() == s.length() ); + + if ( flags & wxELLIPSIZE_FLAGS_PROCESS_MNEMONICS ) + { + // The ampersand itself shouldn't count for the width calculation + // as it won't be displayed: either it's an ampersand before some + // other character in which case it indicates a mnemonic, or it's + // an escaped ampersand, in which case only the second one of the + // pair of ampersands will be displayed. But we can't just remove + // the ampersand as we still need it in the final label, in order + // not to lose the mnemonics. Hence we use this hack, and pretend + // that ampersands simply have zero width. Of course, it could be + // not completely precise, but this is the best we can do without + // completely changing this code structure. + size_t n = 0; + int delta = 0; + for ( wxString::const_iterator it = s.begin(); + it != s.end(); + ++it, ++n ) + { + if ( *it == '&' ) + delta += dc.GetTextExtent(wxS('&')).GetWidth(); + + m_charOffsetsPx[n] -= delta; + } + } } bool IsOk() const { return m_isOk; } @@ -399,12 +429,9 @@ struct EllipsizeCalculator bool m_isOk; }; -} // anonymous namespace - -/* static and protected */ -wxString wxControlBase::DoEllipsizeSingleLine(const wxString& curLine, const wxDC& dc, - wxEllipsizeMode mode, int maxFinalWidthPx, - int replacementWidthPx) +wxString DoEllipsizeSingleLine(const wxString& curLine, const wxDC& dc, + wxEllipsizeMode mode, int maxFinalWidthPx, + int replacementWidthPx, int flags) { wxASSERT_MSG(replacementWidthPx > 0, "Invalid parameters"); wxASSERT_LEVEL_2_MSG(!curLine.Contains('\n'), @@ -412,9 +439,6 @@ wxString wxControlBase::DoEllipsizeSingleLine(const wxString& curLine, const wxD wxASSERT_MSG( mode != wxELLIPSIZE_NONE, "shouldn't be called at all then" ); - // NOTE: this function assumes that any mnemonic/tab character has already - // been handled if it was necessary to handle them (see Ellipsize()) - if (maxFinalWidthPx <= 0) return wxEmptyString; @@ -422,7 +446,7 @@ wxString wxControlBase::DoEllipsizeSingleLine(const wxString& curLine, const wxD if (len <= 1 ) return curLine; - EllipsizeCalculator calc(curLine, dc, maxFinalWidthPx, replacementWidthPx); + EllipsizeCalculator calc(curLine, dc, maxFinalWidthPx, replacementWidthPx, flags); if ( !calc.IsOk() ) return curLine; @@ -519,6 +543,9 @@ wxString wxControlBase::DoEllipsizeSingleLine(const wxString& curLine, const wxD return calc.GetEllipsizedText(); } +} // anonymous namespace + + /* static */ wxString wxControlBase::Ellipsize(const wxString& label, const wxDC& dc, wxEllipsizeMode mode, int maxFinalWidth, @@ -541,7 +568,7 @@ wxString wxControlBase::Ellipsize(const wxString& label, const wxDC& dc, if ( pc == label.end() || *pc == wxS('\n') ) { curLine = DoEllipsizeSingleLine(curLine, dc, mode, maxFinalWidth, - replacementWidth); + replacementWidth, flags); // add this (ellipsized) row to the rest of the label ret << curLine; @@ -551,15 +578,6 @@ wxString wxControlBase::Ellipsize(const wxString& label, const wxDC& dc, ret << *pc; curLine.clear(); } - // we need to remove mnemonics from the label for correct calculations - else if ( *pc == wxS('&') && (flags & wxELLIPSIZE_FLAGS_PROCESS_MNEMONICS) ) - { - // pc+1 is safe: at worst we'll be at end() - wxString::const_iterator next = pc + 1; - if ( next != label.end() && *next == wxS('&') ) - curLine += wxS('&'); // && becomes & - //else: remove this ampersand - } // we need also to expand tabs to properly calc their size else if ( *pc == wxS('\t') && (flags & wxELLIPSIZE_FLAGS_EXPAND_TABS) ) { diff --git a/src/common/stattextcmn.cpp b/src/common/stattextcmn.cpp index 811aceb190..553c607647 100644 --- a/src/common/stattextcmn.cpp +++ b/src/common/stattextcmn.cpp @@ -232,7 +232,7 @@ void wxStaticTextBase::UpdateLabel() if (!IsEllipsized()) return; - wxString newlabel = GetEllipsizedLabel(); + const wxString& newlabel = GetEllipsizedLabel(); // we need to touch the "real" label (i.e. the text set inside the control, // using port-specific functions) instead of the string returned by GetLabel(). @@ -240,9 +240,9 @@ void wxStaticTextBase::UpdateLabel() // In fact, we must be careful not to touch the original label passed to // SetLabel() otherwise GetLabel() will behave in a strange way to the user // (e.g. returning a "Ver...ing" instead of "Very long string") ! - if (newlabel == DoGetLabel()) + if (newlabel == WXGetVisibleLabel()) return; - DoSetLabel(newlabel); + WXSetVisibleLabel(newlabel); } wxString wxStaticTextBase::GetEllipsizedLabel() const diff --git a/src/generic/stattextg.cpp b/src/generic/stattextg.cpp index fe2f13759c..ce32239065 100644 --- a/src/generic/stattextg.cpp +++ b/src/generic/stattextg.cpp @@ -100,7 +100,7 @@ wxSize wxGenericStaticText::DoGetBestClientSize() const void wxGenericStaticText::SetLabel(const wxString& label) { wxControl::SetLabel(label); - DoSetLabel(GetEllipsizedLabel()); + WXSetVisibleLabel(GetEllipsizedLabel()); AutoResizeIfNecessary(); @@ -115,7 +115,7 @@ void wxGenericStaticText::SetLabel(const wxString& label) Refresh(); } -void wxGenericStaticText::DoSetLabel(const wxString& label) +void wxGenericStaticText::WXSetVisibleLabel(const wxString& label) { m_mnemonic = FindAccelIndex(label, &m_label); } diff --git a/src/gtk/stattext.cpp b/src/gtk/stattext.cpp index 36d87b502c..524b6d97b8 100644 --- a/src/gtk/stattext.cpp +++ b/src/gtk/stattext.cpp @@ -270,17 +270,23 @@ void wxStaticText::GTKWidgetDoSetMnemonic(GtkWidget* w) } -// These functions should be used only when GTK+ < 2.6 by wxStaticTextBase::UpdateLabel() +// These functions are not used as GTK supports ellipsization natively and we +// never call the base class UpdateText() which uses them. +// +// Note that, unfortunately, we still need to define them because they still +// exist, as pure virtuals, in the base class even in wxGTK to allow +// wxGenericStaticText to override them. -wxString wxStaticText::DoGetLabel() const +wxString wxStaticText::WXGetVisibleLabel() const { - GtkLabel *label = GTK_LABEL(m_widget); - return wxGTK_CONV_BACK( gtk_label_get_text( label ) ); + wxFAIL_MSG(wxS("Unreachable")); + + return wxString(); } -void wxStaticText::DoSetLabel(const wxString& str) +void wxStaticText::WXSetVisibleLabel(const wxString& WXUNUSED(str)) { - GTKSetLabelForLabel(GTK_LABEL(m_widget), str); + wxFAIL_MSG(wxS("Unreachable")); } // static diff --git a/src/motif/stattext.cpp b/src/motif/stattext.cpp index 44822abbfe..2fdea861ff 100644 --- a/src/motif/stattext.cpp +++ b/src/motif/stattext.cpp @@ -77,12 +77,12 @@ void wxStaticText::SetLabel(const wxString& label) m_labelOrig = label; // save original label // Motif does not support ellipsized labels natively - DoSetLabel(GetEllipsizedLabel()); + WXSetVisibleLabel(GetEllipsizedLabel()); } // for wxST_ELLIPSIZE_* support: -wxString wxStaticText::DoGetLabel() const +wxString wxStaticText::WXGetVisibleLabel() const { XmString label = NULL; XtVaGetValues((Widget)m_labelWidget, XmNlabelString, &label, NULL); @@ -90,7 +90,7 @@ wxString wxStaticText::DoGetLabel() const return wxXmStringToString(label); } -void wxStaticText::DoSetLabel(const wxString& str) +void wxStaticText::WXSetVisibleLabel(const wxString& str) { // build our own cleaned label wxXmString label_str(RemoveMnemonics(str)); diff --git a/src/msw/stattext.cpp b/src/msw/stattext.cpp index f5a29f380e..fd171211a8 100644 --- a/src/msw/stattext.cpp +++ b/src/msw/stattext.cpp @@ -179,10 +179,10 @@ void wxStaticText::SetLabel(const wxString& label) #ifdef SS_ENDELLIPSIS if ( updateStyle.IsOn(SS_ENDELLIPSIS) ) - DoSetLabel(GetLabel()); + WXSetVisibleLabel(GetLabel()); else #endif // SS_ENDELLIPSIS - DoSetLabel(GetEllipsizedLabel()); + WXSetVisibleLabel(GetEllipsizedLabel()); AutoResizeIfNecessary(); } @@ -197,16 +197,18 @@ bool wxStaticText::SetFont(const wxFont& font) return true; } -// for wxST_ELLIPSIZE_* support: +// These functions are used by wxST_ELLIPSIZE_* supporting code in +// wxStaticTextBase which requires us to implement them, but actually the base +// wxWindow methods already do exactly what we need under this platform. -wxString wxStaticText::DoGetLabel() const +wxString wxStaticText::WXGetVisibleLabel() const { - return wxGetWindowText(GetHwnd()); + return wxWindow::GetLabel(); } -void wxStaticText::DoSetLabel(const wxString& str) +void wxStaticText::WXSetVisibleLabel(const wxString& str) { - SetWindowText(GetHwnd(), str.c_str()); + wxWindow::SetLabel(str); } diff --git a/src/osx/stattext_osx.cpp b/src/osx/stattext_osx.cpp index 53e0e0ced9..cea4cf5c19 100644 --- a/src/osx/stattext_osx.cpp +++ b/src/osx/stattext_osx.cpp @@ -71,11 +71,11 @@ void wxStaticText::SetLabel(const wxString& label) ) { // leave ellipsization to the OS - DoSetLabel(GetLabel()); + WXSetVisibleLabel(GetLabel()); } else // not supported natively { - DoSetLabel(GetEllipsizedLabel()); + WXSetVisibleLabel(GetEllipsizedLabel()); } AutoResizeIfNecessary(); @@ -98,7 +98,7 @@ bool wxStaticText::SetFont(const wxFont& font) return ret; } -void wxStaticText::DoSetLabel(const wxString& label) +void wxStaticText::WXSetVisibleLabel(const wxString& label) { m_label = RemoveMnemonics(label); GetPeer()->SetLabel(m_label , GetFont().GetEncoding() ); @@ -118,7 +118,7 @@ bool wxStaticText::DoSetLabelMarkup(const wxString& markup) #endif // wxUSE_MARKUP && wxOSX_USE_COCOA -wxString wxStaticText::DoGetLabel() const +wxString wxStaticText::WXGetVisibleLabel() const { return m_label; } diff --git a/src/qt/stattext.cpp b/src/qt/stattext.cpp index f6d2bcde63..369d15f7e2 100644 --- a/src/qt/stattext.cpp +++ b/src/qt/stattext.cpp @@ -68,11 +68,26 @@ bool wxStaticText::Create(wxWindow *parent, } void wxStaticText::SetLabel(const wxString& label) +{ + // If the label doesn't really change, avoid flicker by not doing anything. + if ( label == m_labelOrig ) + return; + + // save the label in m_labelOrig with both the markup (if any) and + // the mnemonics characters (if any) + m_labelOrig = label; + + WXSetVisibleLabel(GetEllipsizedLabel()); + + AutoResizeIfNecessary(); +} + +void wxStaticText::WXSetVisibleLabel(const wxString& label) { m_qtLabel->setText( wxQtConvertString( label ) ); } -wxString wxStaticText::GetLabel() const +wxString wxStaticText::WXGetVisibleLabel() const { return wxQtConvertString( m_qtLabel->text() ); } diff --git a/src/univ/stattext.cpp b/src/univ/stattext.cpp index a79338873c..7d25958ad9 100644 --- a/src/univ/stattext.cpp +++ b/src/univ/stattext.cpp @@ -77,15 +77,15 @@ void wxStaticText::SetLabel(const wxString& str) m_labelOrig = str; // draw as real label the abbreviated version of it - DoSetLabel(GetEllipsizedLabel()); + WXSetVisibleLabel(GetEllipsizedLabel()); } -void wxStaticText::DoSetLabel(const wxString& str) +void wxStaticText::WXSetVisibleLabel(const wxString& str) { UnivDoSetLabel(str); } -wxString wxStaticText::DoGetLabel() const +wxString wxStaticText::WXGetVisibleLabel() const { return wxControl::GetLabel(); } diff --git a/tests/controls/label.cpp b/tests/controls/label.cpp index 3ba89c2f7e..94806a8cd7 100644 --- a/tests/controls/label.cpp +++ b/tests/controls/label.cpp @@ -20,176 +20,120 @@ #include "wx/app.h" #endif // WX_PRECOMP -#include "wx/control.h" -#include "wx/stattext.h" #include "wx/checkbox.h" +#include "wx/control.h" +#include "wx/scopedptr.h" +#include "wx/stattext.h" -// ---------------------------------------------------------------------------- -// test class -// ---------------------------------------------------------------------------- +#include "wx/generic/stattextg.h" -class LabelTestCase : public CppUnit::TestCase +namespace { -public: - LabelTestCase() { } - virtual void setUp() wxOVERRIDE; - virtual void tearDown() wxOVERRIDE; +const char* const ORIGINAL_LABEL = "origin label"; -private: - CPPUNIT_TEST_SUITE( LabelTestCase ); - CPPUNIT_TEST( GetLabel ); - CPPUNIT_TEST( GetLabelText ); - CPPUNIT_TEST( Statics ); - CPPUNIT_TEST_SUITE_END(); - - void GetLabel(); - void GetLabelText(); - void Statics(); - - wxStaticText *m_st; - - // we cannot test wxControl directly (it's abstract) so we rather test wxCheckBox - wxCheckBox *m_cb; - - wxDECLARE_NO_COPY_CLASS(LabelTestCase); -}; - -// register in the unnamed registry so that these tests are run by default -CPPUNIT_TEST_SUITE_REGISTRATION( LabelTestCase ); - -// also include in its own registry so that these tests can be run alone -CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( LabelTestCase, "LabelTestCase" ); - -// ---------------------------------------------------------------------------- -// test initialization -// ---------------------------------------------------------------------------- - -#define ORIGINAL_LABEL "original label" - -void LabelTestCase::setUp() +// The actual testing function. It will change the label of the provided +// control, which is assumed to be ORIGINAL_LABEL initially. +void DoTestLabel(wxControl* c) { - m_st = new wxStaticText(wxTheApp->GetTopWindow(), wxID_ANY, ORIGINAL_LABEL); + CHECK( c->GetLabel() == ORIGINAL_LABEL ); - m_cb = new wxCheckBox(wxTheApp->GetTopWindow(), wxID_ANY, ORIGINAL_LABEL); - - CPPUNIT_ASSERT_EQUAL( ORIGINAL_LABEL, m_st->GetLabel() ); - CPPUNIT_ASSERT_EQUAL( ORIGINAL_LABEL, m_cb->GetLabel() ); -} - -void LabelTestCase::tearDown() -{ - wxDELETE(m_st); - wxDELETE(m_cb); -} - -// ---------------------------------------------------------------------------- -// the tests themselves -// ---------------------------------------------------------------------------- - -#define SET_LABEL(str) \ - m_st->SetLabel(str); \ - m_cb->SetLabel(str); - -#define SET_LABEL_TEXT(str) \ - m_st->SetLabelText(str); \ - m_cb->SetLabelText(str); - -void LabelTestCase::GetLabel() -{ const wxString testLabelArray[] = { "label without mnemonics and markup", "label with &mnemonic", "label with some markup", "label with some markup and &mnemonic", + "label with an && (ampersand)", + "label with an && (&ersand)", + "", // empty label should work too }; - // test calls to SetLabel() and then to GetLabel() - for ( unsigned int s = 0; s < WXSIZEOF(testLabelArray); s++ ) { - SET_LABEL(testLabelArray[s]); + const wxString& l = testLabelArray[s]; // GetLabel() should always return the string passed to SetLabel() - CPPUNIT_ASSERT_EQUAL( testLabelArray[s], m_st->GetLabel() ); - CPPUNIT_ASSERT_EQUAL( testLabelArray[s], m_cb->GetLabel() ); - } + c->SetLabel(l); + CHECK( c->GetLabel() == l ); - - // test calls to SetLabelText() and then to GetLabel() - - const wxString& testLabel = "label without mnemonics and markup"; - SET_LABEL_TEXT(testLabel); - CPPUNIT_ASSERT_EQUAL( testLabel, m_st->GetLabel() ); - CPPUNIT_ASSERT_EQUAL( testLabel, m_cb->GetLabel() ); - - const wxString& testLabel2 = "label with &mnemonic"; - const wxString& testLabelText2 = "label with &&mnemonic"; - SET_LABEL_TEXT(testLabel2); - CPPUNIT_ASSERT_EQUAL( testLabelText2, m_st->GetLabel() ); - CPPUNIT_ASSERT_EQUAL( testLabelText2, m_cb->GetLabel() ); - - const wxString& testLabel3 = "label with some markup"; - SET_LABEL_TEXT(testLabel3); - CPPUNIT_ASSERT_EQUAL( testLabel3, m_st->GetLabel() ); - CPPUNIT_ASSERT_EQUAL( testLabel3, m_cb->GetLabel() ); - - const wxString& testLabel4 = "label with some markup and &mnemonic"; - const wxString& testLabelText4 = "label with some markup and &&mnemonic"; - SET_LABEL_TEXT(testLabel4); - CPPUNIT_ASSERT_EQUAL( testLabelText4, m_st->GetLabel() ); - CPPUNIT_ASSERT_EQUAL( testLabelText4, m_cb->GetLabel() ); -} - -void LabelTestCase::GetLabelText() -{ - // test calls to SetLabel() and then to GetLabelText() - - const wxString& testLabel = "label without mnemonics and markup"; - SET_LABEL(testLabel); - CPPUNIT_ASSERT_EQUAL( testLabel, m_st->GetLabelText() ); - CPPUNIT_ASSERT_EQUAL( testLabel, m_cb->GetLabelText() ); - - const wxString& testLabel2 = "label with &mnemonic"; - const wxString& testLabelText2 = "label with mnemonic"; - SET_LABEL(testLabel2); - CPPUNIT_ASSERT_EQUAL( testLabelText2, m_st->GetLabelText() ); - CPPUNIT_ASSERT_EQUAL( testLabelText2, m_cb->GetLabelText() ); - - const wxString& testLabel3 = "label with some markup"; - SET_LABEL(testLabel3); - CPPUNIT_ASSERT_EQUAL( testLabel3, m_st->GetLabelText() ); - CPPUNIT_ASSERT_EQUAL( testLabel3, m_cb->GetLabelText() ); - - const wxString& testLabel4 = "label with some markup and &mnemonic"; - const wxString& testLabelText4 = "label with some markup and mnemonic"; - SET_LABEL(testLabel4); - CPPUNIT_ASSERT_EQUAL( testLabelText4, m_st->GetLabelText() ); - CPPUNIT_ASSERT_EQUAL( testLabelText4, m_cb->GetLabelText() ); - - - const wxString testLabelArray[] = { - "label without mnemonics and markup", - "label with &mnemonic", - "label with some markup", - "label with some markup and &mnemonic", - }; - - // test calls to SetLabelText() and then to GetLabelText() - - for ( unsigned int s = 0; s < WXSIZEOF(testLabelArray); s++ ) - { - SET_LABEL_TEXT(testLabelArray[s]); + // GetLabelText() should always return unescaped version of the label + CHECK( c->GetLabelText() == wxControl::RemoveMnemonics(l) ); // GetLabelText() should always return the string passed to SetLabelText() - CPPUNIT_ASSERT_EQUAL( testLabelArray[s], m_st->GetLabelText() ); - CPPUNIT_ASSERT_EQUAL( testLabelArray[s], m_cb->GetLabelText() ); + c->SetLabelText(l); + CHECK( c->GetLabelText() == l ); + + // And GetLabel() should be the escaped version of the text + CHECK( l == wxControl::RemoveMnemonics(c->GetLabel()) ); + } + + // Check that both "&" and "&" work in markup. +#if wxUSE_MARKUP + c->SetLabelMarkup("mnemonic in &markup"); + CHECK( c->GetLabel() == "mnemonic in &markup" ); + CHECK( c->GetLabelText() == "mnemonic in markup" ); + + c->SetLabelMarkup("mnemonic in &markup"); + CHECK( c->GetLabel() == "mnemonic in &markup" ); + CHECK( c->GetLabelText() == "mnemonic in markup" ); + + c->SetLabelMarkup("&& finally"); + CHECK( c->GetLabel() == "&& finally" ); + CHECK( c->GetLabelText() == "& finally" ); + + c->SetLabelMarkup("&& finally"); + CHECK( c->GetLabel() == "&& finally" ); + CHECK( c->GetLabelText() == "& finally" ); +#endif // wxUSE_MARKUP +} + +} // anonymous namespace + +TEST_CASE("wxControl::Label", "[wxControl][label]") +{ + SECTION("wxStaticText") + { + const wxScopedPtr + st(new wxStaticText(wxTheApp->GetTopWindow(), wxID_ANY, ORIGINAL_LABEL)); + DoTestLabel(st.get()); + } + + SECTION("wxStaticText/ellipsized") + { + const wxScopedPtr + st(new wxStaticText(wxTheApp->GetTopWindow(), wxID_ANY, ORIGINAL_LABEL, + wxDefaultPosition, wxDefaultSize, + wxST_ELLIPSIZE_START)); + DoTestLabel(st.get()); + } + + SECTION("wxGenericStaticText") + { + const wxScopedPtr + gst(new wxGenericStaticText(wxTheApp->GetTopWindow(), wxID_ANY, ORIGINAL_LABEL)); + DoTestLabel(gst.get()); + } + + SECTION("wxCheckBox") + { + const wxScopedPtr + cb(new wxCheckBox(wxTheApp->GetTopWindow(), wxID_ANY, ORIGINAL_LABEL)); + DoTestLabel(cb.get()); } } -void LabelTestCase::Statics() +TEST_CASE("wxControl::RemoveMnemonics", "[wxControl][label][mnemonics]") { - CPPUNIT_ASSERT_EQUAL( "mnemonic", wxControl::RemoveMnemonics("&mnemonic") ); - CPPUNIT_ASSERT_EQUAL( "&mnemonic", wxControl::RemoveMnemonics("&&mnemonic") ); - CPPUNIT_ASSERT_EQUAL( "&mnemonic", wxControl::RemoveMnemonics("&&&mnemonic") ); + CHECK( "mnemonic" == wxControl::RemoveMnemonics("&mnemonic") ); + CHECK( "&mnemonic" == wxControl::RemoveMnemonics("&&mnemonic") ); + CHECK( "&mnemonic" == wxControl::RemoveMnemonics("&&&mnemonic") ); +} + +TEST_CASE("wxControl::FindAccelIndex", "[wxControl][label][mnemonics]") +{ + CHECK( wxControl::FindAccelIndex("foo") == wxNOT_FOUND ); + CHECK( wxControl::FindAccelIndex("&foo") == 0 ); + CHECK( wxControl::FindAccelIndex("f&oo") == 1 ); + CHECK( wxControl::FindAccelIndex("foo && bar") == wxNOT_FOUND ); + CHECK( wxControl::FindAccelIndex("foo && &bar") == 6 ); } diff --git a/tests/graphics/ellipsization.cpp b/tests/graphics/ellipsization.cpp index 2a584762f2..d7c90242b7 100644 --- a/tests/graphics/ellipsization.cpp +++ b/tests/graphics/ellipsization.cpp @@ -108,6 +108,16 @@ void EllipsizationTestCase::NormalCase() flagsToTest[f] ); + // Note that we must measure the width of the text that + // will be rendered, and when mnemonics are used, this + // means we have to remove them first. + const wxString + displayed = flagsToTest[f] & wxELLIPSIZE_FLAGS_PROCESS_MNEMONICS + ? wxControl::RemoveMnemonics(ret) + : ret; + const int + width = dc.GetMultiLineTextExtent(displayed).GetWidth(); + WX_ASSERT_MESSAGE ( ( @@ -115,10 +125,10 @@ void EllipsizationTestCase::NormalCase() s, f, m, str, ret, - dc.GetMultiLineTextExtent(ret).GetWidth(), + width, widthsToTest[w] ), - dc.GetMultiLineTextExtent(ret).GetWidth() <= widthsToTest[w] + width <= widthsToTest[w] ); } }