refactor wxStaticText::Ellipsize so it's a static public utility function; document it and a couple of other useful functions

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57622 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Francesco Montorsi
2008-12-28 19:24:13 +00:00
parent 9140731891
commit 4520d5836a
4 changed files with 163 additions and 83 deletions

View File

@@ -24,10 +24,14 @@
#define wxST_NO_AUTORESIZE 0x0001 #define wxST_NO_AUTORESIZE 0x0001
#define wxST_MARKUP 0x0002 #define wxST_MARKUP 0x0002
#define wxST_ELLIPSIZE_START 0x0004 // NOTE: the members of this enum are used both as window styles for wxStaticText
#define wxST_ELLIPSIZE_MIDDLE 0x0008 // and both as enumeration values for wxStaticText::Ellipsize static function
#define wxST_ELLIPSIZE_END 0x0010 enum wxEllipsizeMode
{
wxST_ELLIPSIZE_START = 0x0004,
wxST_ELLIPSIZE_MIDDLE = 0x0008,
wxST_ELLIPSIZE_END = 0x0010
};
extern WXDLLIMPEXP_DATA_CORE(const char) wxStaticTextNameStr[]; extern WXDLLIMPEXP_DATA_CORE(const char) wxStaticTextNameStr[];
@@ -65,10 +69,13 @@ public:
// and then returns the cleaned string // and then returns the cleaned string
static wxString RemoveMarkup(const wxString& str); static wxString RemoveMarkup(const wxString& str);
// escapes the alls special symbols (<>"'&) present inside the given string // escapes all special symbols (<>"'&) present in the given string
// using the corresponding entities (&lt; &gt; &quot; &apos; &amp;) // using the corresponding entities (&lt; &gt; &quot; &apos; &amp;)
static wxString EscapeMarkup(const wxString& str); static wxString EscapeMarkup(const wxString& str);
// replaces parts of the string with ellipsis if needed
static wxString Ellipsize(const wxString& label, const wxDC& dc,
wxEllipsizeMode mode, int maxWidth);
protected: // functions required for wxST_ELLIPSIZE_* support protected: // functions required for wxST_ELLIPSIZE_* support

View File

@@ -43,18 +43,23 @@ public:
wxString GetLabelText() const; wxString GetLabelText() const;
/** /**
Returns the given @a label string without mnemonics. Returns the given @a label string without mnemonics ("&" characters).
*/ */
static wxString GetLabelText(const wxString& label); static wxString GetLabelText(const wxString& label);
/**
Removes the mnemonics ("&" characters) from the given string.
*/
static wxString RemoveMnemonics(const wxString& str);
/** /**
Sets the item's text. Sets the item's text.
Any "&" characters in the @a label are special and indicate that the Any "&" characters in the @a label are special and indicate that the
following character is a mnemonic for this control and can be used to following character is a @e mnemonic for this control and can be used to
activate it from the keyboard (typically by using @e Alt key in activate it from the keyboard (typically by using @e Alt key in
combination with it). To insert a literal ampersand character, you need combination with it).
to double it, i.e. use "&&". To insert a literal ampersand character, you need to double it, i.e. use "&&".
*/ */
void SetLabel(const wxString& label); void SetLabel(const wxString& label);
}; };

View File

@@ -6,10 +6,27 @@
// Licence: wxWindows license // Licence: wxWindows license
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
/**
The different ellipsization modes supported by wxStaticText and by
wxStaticText::Ellipsize function.
@note
The members of this enum are used both as window styles for wxStaticText
and both as enumeration values for wxStaticText::Ellipsize static function.
*/
enum wxEllipsizeMode
{
wxST_ELLIPSIZE_START = 0x0004,
wxST_ELLIPSIZE_MIDDLE = 0x0008,
wxST_ELLIPSIZE_END = 0x0010
};
/** /**
@class wxStaticText @class wxStaticText
A static text control displays one or more lines of read-only text. A static text control displays one or more lines of read-only text.
wxStaticText supports the three classic text alignments, label ellipsization
and formatting markup.
@beginStyleTable @beginStyleTable
@style{wxALIGN_LEFT} @style{wxALIGN_LEFT}
@@ -26,15 +43,16 @@
CENTER style because otherwise they won't make sense any longer CENTER style because otherwise they won't make sense any longer
after a call to SetLabel) after a call to SetLabel)
@style{wxST_ELLIPSIZE_START} @style{wxST_ELLIPSIZE_START}
If the text width exceeds the control width, replace the beginning If the labeltext width exceeds the control width, replace the beginning
of the text with an ellipsis of the label with an ellipsis
@style{wxST_ELLIPSIZE_MIDDLE} @style{wxST_ELLIPSIZE_MIDDLE}
Same as above, but replace the text in the middle of the control If the label text width exceeds the control width, replace the middle
with an ellipsis of the label with an ellipsis
@style{wxST_ELLIPSIZE_END} @style{wxST_ELLIPSIZE_END}
Same as above, but replace the end of the text with an ellipsis If the label text width exceeds the control width, replace the end
of the label with an ellipsis
@style{wxST_MARKUP} @style{wxST_MARKUP}
Support markup in the label; see SetLabel for more information Support markup in the label; see SetLabel() for more information
@endStyleTable @endStyleTable
@library{wxcore} @library{wxcore}
@@ -86,6 +104,30 @@ public:
const wxSize& size = wxDefaultSize, long style = 0, const wxSize& size = wxDefaultSize, long style = 0,
const wxString& name = wxStaticTextNameStr); const wxString& name = wxStaticTextNameStr);
/**
Escapes all the symbols of @a str that have a special meaning (<tt><>"'&</tt>) for
wxStaticText objects with the @c wxST_MARKUP style.
Those symbols are replaced the corresponding entities (&lt; &gt; &quot; &apos; &amp;).
*/
static wxString EscapeMarkup(const wxString& str);
/**
Replaces parts of the @a label string with ellipsis, if needed, so
that it doesn't exceed @a maxWidth.
@param label
The string to ellipsize
@param dc
The DC used to retrieve the character widths through the
wxDC::GetPartialTextExtents() function.
@param mode
The ellipsization modes. See ::wxEllipsizeMode.
@param maxWidth
The maximum width of the returned string in pixels.
*/
static wxString Ellipsize(const wxString& label, const wxDC& dc,
wxEllipsizeMode mode, int maxWidth);
/** /**
Returns the contents of the control. Returns the contents of the control.
@@ -107,6 +149,20 @@ public:
*/ */
static wxString GetLabelText(const wxString& label); static wxString GetLabelText(const wxString& label);
/**
Returns @true if the window styles for this control contains one of the
@c wxST_ELLIPSIZE_START, @c wxST_ELLIPSIZE_MIDDLE or @c wxST_ELLIPSIZE_END styles.
*/
bool IsEllipsized() const;
/**
Removes the markup accepted by wxStaticText when the @c wxST_MARKUP style is used,
and then returns the cleaned string.
See SetLabel() for more info about the markup.
*/
static wxString RemoveMarkup(const wxString& str);
/** /**
Sets the static text label and updates the controls size to exactly fit the Sets the static text label and updates the controls size to exactly fit the
label unless the control has wxST_NO_AUTORESIZE flag. label unless the control has wxST_NO_AUTORESIZE flag.

View File

@@ -269,63 +269,12 @@ wxString wxStaticTextBase::EscapeMarkup(const wxString& text)
return ret; return ret;
} }
// ----------------------------------------------------------------------------
// wxStaticTextBase - generic implementation for wxST_ELLIPSIZE_* support
// ----------------------------------------------------------------------------
void wxStaticTextBase::UpdateLabel()
{
if (!IsEllipsized())
return;
wxString newlabel = GetEllipsizedLabelWithoutMarkup();
// 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().
//
// 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())
return;
DoSetLabel(newlabel);
}
wxString wxStaticTextBase::GetEllipsizedLabelWithoutMarkup() const
{
// this function should be used only by ports which do not support
// ellipsis in static texts: we first remove markup (which cannot
// be handled safely by Ellipsize()) and then ellipsize the result.
wxString ret(m_labelOrig);
// the order of the following two blocks is important!
if (HasFlag(wxST_MARKUP))
ret = RemoveMarkup(ret);
if (IsEllipsized())
ret = Ellipsize(ret);
return ret;
}
#define wxELLIPSE_REPLACEMENT wxT("...") #define wxELLIPSE_REPLACEMENT wxT("...")
wxString wxStaticTextBase::Ellipsize(const wxString& label) const /* static */
wxString wxStaticTextBase::Ellipsize(const wxString& label, const wxDC& dc,
wxEllipsizeMode mode, int maxFinalWidth)
{ {
wxSize sz(GetSize());
if (sz.GetWidth() < 2 || sz.GetHeight() < 2)
{
// the size of this window is not valid (yet)
return label;
}
wxClientDC dc(const_cast<wxStaticTextBase*>(this));
dc.SetFont(GetFont());
wxArrayInt charOffsets; wxArrayInt charOffsets;
wxString ret; wxString ret;
@@ -333,7 +282,7 @@ wxString wxStaticTextBase::Ellipsize(const wxString& label) const
int replacementWidth = dc.GetTextExtent(wxELLIPSE_REPLACEMENT).GetWidth(); int replacementWidth = dc.GetTextExtent(wxELLIPSE_REPLACEMENT).GetWidth();
int marginWidth = dc.GetCharWidth()*2; int marginWidth = dc.GetCharWidth()*2;
// handle correctly labels with newlines // NB: we must handle correctly labels with newlines:
wxString curLine; wxString curLine;
wxSize reqsize; wxSize reqsize;
size_t len; size_t len;
@@ -348,17 +297,17 @@ wxString wxStaticTextBase::Ellipsize(const wxString& label) const
wxASSERT(charOffsets.GetCount() == len); wxASSERT(charOffsets.GetCount() == len);
size_t totalWidth = charOffsets.Last(); size_t totalWidth = charOffsets.Last();
if ( totalWidth > (size_t)sz.GetWidth() ) if ( totalWidth > (size_t)maxFinalWidth )
{ {
// we need to ellipsize this row // we need to ellipsize this row
int excessPixels = totalWidth - sz.GetWidth() + int excessPixels = totalWidth - maxFinalWidth +
replacementWidth + replacementWidth +
marginWidth; // security margin (NEEDED!) marginWidth; // security margin (NEEDED!)
// remove characters in excess // remove characters in excess
size_t initialChar, // index of first char to erase size_t initialChar, // index of first char to erase
nChars; // how many chars do we need to erase? nChars; // how many chars do we need to erase?
if (HasFlag(wxST_ELLIPSIZE_START)) if (mode == wxST_ELLIPSIZE_START)
{ {
initialChar = 0; initialChar = 0;
for (nChars=0; for (nChars=0;
@@ -366,7 +315,7 @@ wxString wxStaticTextBase::Ellipsize(const wxString& label) const
nChars++) nChars++)
; ;
} }
else if (HasFlag(wxST_ELLIPSIZE_MIDDLE)) else if (mode == wxST_ELLIPSIZE_MIDDLE)
{ {
// the start & end of the removed span of chars // the start & end of the removed span of chars
initialChar = len/2; initialChar = len/2;
@@ -410,7 +359,7 @@ wxString wxStaticTextBase::Ellipsize(const wxString& label) const
} }
else else
{ {
wxASSERT(HasFlag(wxST_ELLIPSIZE_END)); wxASSERT(mode == wxST_ELLIPSIZE_END);
wxASSERT(len > 0); wxASSERT(len > 0);
int maxWidth = totalWidth - excessPixels; int maxWidth = totalWidth - excessPixels;
@@ -442,13 +391,13 @@ wxString wxStaticTextBase::Ellipsize(const wxString& label) const
curLine.erase(initialChar, nChars+1); curLine.erase(initialChar, nChars+1);
// if there is space for the replacement dots, add them // if there is space for the replacement dots, add them
if (sz.GetWidth() > replacementWidth) if (maxFinalWidth > replacementWidth)
curLine.insert(initialChar, wxELLIPSE_REPLACEMENT); curLine.insert(initialChar, wxELLIPSE_REPLACEMENT);
} }
// if everything was ok, we should have shortened this line // if everything was ok, we should have shortened this line
// enough to make it fit in sz.GetWidth(): // enough to make it fit in sz.maxFinalWidth:
wxASSERT(dc.GetTextExtent(curLine).GetWidth() < sz.GetWidth()); wxASSERT(dc.GetTextExtent(curLine).GetWidth() < maxFinalWidth);
} }
} }
@@ -485,7 +434,70 @@ wxString wxStaticTextBase::Ellipsize(const wxString& label) const
} }
} }
//return ret; return ret;
}
// ----------------------------------------------------------------------------
// wxStaticTextBase - generic implementation for wxST_ELLIPSIZE_* support
// ----------------------------------------------------------------------------
void wxStaticTextBase::UpdateLabel()
{
if (!IsEllipsized())
return;
wxString newlabel = GetEllipsizedLabelWithoutMarkup();
// 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().
//
// 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())
return;
DoSetLabel(newlabel);
}
wxString wxStaticTextBase::GetEllipsizedLabelWithoutMarkup() const
{
// this function should be used only by ports which do not support
// ellipsis in static texts: we first remove markup (which cannot
// be handled safely by Ellipsize()) and then ellipsize the result.
wxString ret(m_labelOrig);
// the order of the following two blocks is important!
if (HasFlag(wxST_MARKUP))
ret = RemoveMarkup(ret);
if (IsEllipsized())
ret = Ellipsize(ret);
return ret;
}
wxString wxStaticTextBase::Ellipsize(const wxString& label) const
{
wxSize sz(GetSize());
if (sz.GetWidth() < 2 || sz.GetHeight() < 2)
{
// the size of this window is not valid (yet)
return label;
}
wxClientDC dc(const_cast<wxStaticTextBase*>(this));
dc.SetFont(GetFont());
wxEllipsizeMode mode;
if (HasFlag(wxST_ELLIPSIZE_START)) mode = wxST_ELLIPSIZE_START;
else if (HasFlag(wxST_ELLIPSIZE_MIDDLE)) mode = wxST_ELLIPSIZE_MIDDLE;
else if (HasFlag(wxST_ELLIPSIZE_END)) mode = wxST_ELLIPSIZE_END;
return Ellipsize(label, dc, mode, sz.GetWidth());
} }
#endif // wxUSE_STATTEXT #endif // wxUSE_STATTEXT