Preserve mnemonics in ellipsized labels
Ellipsization code was completely broken when used with the usual control label strings containing mnemonics: it simply stripped the mnemonics completely, losing them even if the label wasn't actually ellipsized, and turned "&&" into a mnemonic. I.e. "&Plug && play" appeared without underlined "P" but with underlined space before "play" before. Fix this by pretending that all ampersands in the string to be ellipsized have zero width. This is not precise, as the result of GetPartialTextExtents() for a string with the ampersands is not exactly the same as the sum of its result for the string without the ampersands and the width of the ampersands themselves, but it should be pretty close and unlikely to result in any problems in practice for the controls labels. At the very least this fixes the completely wrong behaviour of the controls on the "Static" page of the widgets sample, where ellipsization is enabled by default and setting the label text with mnemonics didn't work at all.
This commit is contained in:
@@ -282,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),
|
||||
@@ -294,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; }
|
||||
@@ -405,7 +431,7 @@ struct EllipsizeCalculator
|
||||
|
||||
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'),
|
||||
@@ -413,9 +439,6 @@ wxString DoEllipsizeSingleLine(const wxString& curLine, const wxDC& dc,
|
||||
|
||||
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;
|
||||
|
||||
@@ -423,7 +446,7 @@ wxString DoEllipsizeSingleLine(const wxString& curLine, const wxDC& dc,
|
||||
if (len <= 1 )
|
||||
return curLine;
|
||||
|
||||
EllipsizeCalculator calc(curLine, dc, maxFinalWidthPx, replacementWidthPx);
|
||||
EllipsizeCalculator calc(curLine, dc, maxFinalWidthPx, replacementWidthPx, flags);
|
||||
|
||||
if ( !calc.IsOk() )
|
||||
return curLine;
|
||||
@@ -545,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;
|
||||
@@ -555,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) )
|
||||
{
|
||||
|
Reference in New Issue
Block a user