Merge branch 'statictext-setlabel'

wxControl label-related fixes and improvements.

See https://github.com/wxWidgets/wxWidgets/pull/1364
This commit is contained in:
Vadim Zeitlin
2019-07-08 10:09:49 +02:00
21 changed files with 238 additions and 265 deletions

View File

@@ -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.

View File

@@ -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;

View File

@@ -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

View File

@@ -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:

View File

@@ -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);
};

View File

@@ -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;

View File

@@ -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;

View File

@@ -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.

View File

@@ -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);
};

View File

@@ -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 <b>decorated</b> "
"with <u>markup</u>; here you need entities "
"for the symbols: &lt; &gt; &amp; &apos; &quot; "
" but you can still place &mnemonics...");
"for the symbols: &lt; &gt; &amp;&amp; &apos; &quot; "
" 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<wxObject*>(m_chkEllipsize))
{
m_radioEllipsize->Enable(event.IsChecked());
}
CreateStatic();
}

View File

@@ -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,
wxString DoEllipsizeSingleLine(const wxString& curLine, const wxDC& dc,
wxEllipsizeMode mode, int maxFinalWidthPx,
int replacementWidthPx)
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) )
{

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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));

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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() );
}

View File

@@ -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();
}

View File

@@ -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 <span foreground='blue'>some</span> <b>markup</b>",
"label with <span foreground='blue'>some</span> <b>markup</b> and &mnemonic",
"label with an && (ampersand)",
"label with an && (&ampersand)",
"", // 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 <span foreground='blue'>some</span> <b>markup</b>";
SET_LABEL_TEXT(testLabel3);
CPPUNIT_ASSERT_EQUAL( testLabel3, m_st->GetLabel() );
CPPUNIT_ASSERT_EQUAL( testLabel3, m_cb->GetLabel() );
const wxString& testLabel4 = "label with <span foreground='blue'>some</span> <b>markup</b> and &mnemonic";
const wxString& testLabelText4 = "label with <span foreground='blue'>some</span> <b>markup</b> 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 <span foreground='blue'>some</span> <b>markup</b>";
SET_LABEL(testLabel3);
CPPUNIT_ASSERT_EQUAL( testLabel3, m_st->GetLabelText() );
CPPUNIT_ASSERT_EQUAL( testLabel3, m_cb->GetLabelText() );
const wxString& testLabel4 = "label with <span foreground='blue'>some</span> <b>markup</b> and &mnemonic";
const wxString& testLabelText4 = "label with <span foreground='blue'>some</span> <b>markup</b> 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 <span foreground='blue'>some</span> <b>markup</b>",
"label with <span foreground='blue'>some</span> <b>markup</b> 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 "&amp;" work in markup.
#if wxUSE_MARKUP
c->SetLabelMarkup("mnemonic in &amp;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("&amp;&amp; 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<wxStaticText>
st(new wxStaticText(wxTheApp->GetTopWindow(), wxID_ANY, ORIGINAL_LABEL));
DoTestLabel(st.get());
}
SECTION("wxStaticText/ellipsized")
{
const wxScopedPtr<wxStaticText>
st(new wxStaticText(wxTheApp->GetTopWindow(), wxID_ANY, ORIGINAL_LABEL,
wxDefaultPosition, wxDefaultSize,
wxST_ELLIPSIZE_START));
DoTestLabel(st.get());
}
SECTION("wxGenericStaticText")
{
const wxScopedPtr<wxGenericStaticText>
gst(new wxGenericStaticText(wxTheApp->GetTopWindow(), wxID_ANY, ORIGINAL_LABEL));
DoTestLabel(gst.get());
}
SECTION("wxCheckBox")
{
const wxScopedPtr<wxCheckBox>
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 );
}

View File

@@ -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]
);
}
}