From 4520d5836a52526c64e5b9469e6acee2221476d2 Mon Sep 17 00:00:00 2001 From: Francesco Montorsi Date: Sun, 28 Dec 2008 19:24:13 +0000 Subject: [PATCH] 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 --- include/wx/stattext.h | 17 +++-- interface/wx/control.h | 13 +++- interface/wx/stattext.h | 68 +++++++++++++++-- src/common/stattextcmn.cpp | 148 ++++++++++++++++++++----------------- 4 files changed, 163 insertions(+), 83 deletions(-) diff --git a/include/wx/stattext.h b/include/wx/stattext.h index 1aef30c9a4..69cee4fc97 100644 --- a/include/wx/stattext.h +++ b/include/wx/stattext.h @@ -24,10 +24,14 @@ #define wxST_NO_AUTORESIZE 0x0001 #define wxST_MARKUP 0x0002 -#define wxST_ELLIPSIZE_START 0x0004 -#define wxST_ELLIPSIZE_MIDDLE 0x0008 -#define wxST_ELLIPSIZE_END 0x0010 - +// 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 +}; extern WXDLLIMPEXP_DATA_CORE(const char) wxStaticTextNameStr[]; @@ -65,10 +69,13 @@ public: // and then returns the cleaned string 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 (< > " ' &) 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 diff --git a/interface/wx/control.h b/interface/wx/control.h index 3feb1b59b4..837c91521d 100644 --- a/interface/wx/control.h +++ b/interface/wx/control.h @@ -43,18 +43,23 @@ public: 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); + /** + Removes the mnemonics ("&" characters) from the given string. + */ + static wxString RemoveMnemonics(const wxString& str); + /** Sets the item's text. 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 - combination with it). To insert a literal ampersand character, you need - to double it, i.e. use "&&". + combination with it). + To insert a literal ampersand character, you need to double it, i.e. use "&&". */ void SetLabel(const wxString& label); }; diff --git a/interface/wx/stattext.h b/interface/wx/stattext.h index 21d1affe1b..aa5097f25b 100644 --- a/interface/wx/stattext.h +++ b/interface/wx/stattext.h @@ -6,10 +6,27 @@ // 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 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 @style{wxALIGN_LEFT} @@ -26,15 +43,16 @@ CENTER style because otherwise they won't make sense any longer after a call to SetLabel) @style{wxST_ELLIPSIZE_START} - If the text width exceeds the control width, replace the beginning - of the text with an ellipsis + If the labeltext width exceeds the control width, replace the beginning + of the label with an ellipsis @style{wxST_ELLIPSIZE_MIDDLE} - Same as above, but replace the text in the middle of the control - with an ellipsis + If the label text width exceeds the control width, replace the middle + of the label with an ellipsis @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} - Support markup in the label; see SetLabel for more information + Support markup in the label; see SetLabel() for more information @endStyleTable @library{wxcore} @@ -86,6 +104,30 @@ public: const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxStaticTextNameStr); + /** + Escapes all the symbols of @a str that have a special meaning (<>"'&) for + wxStaticText objects with the @c wxST_MARKUP style. + Those symbols are replaced the corresponding entities (< > " ' &). + */ + 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. @@ -107,6 +149,20 @@ public: */ 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 label unless the control has wxST_NO_AUTORESIZE flag. diff --git a/src/common/stattextcmn.cpp b/src/common/stattextcmn.cpp index b2ac7a044c..33992dc246 100644 --- a/src/common/stattextcmn.cpp +++ b/src/common/stattextcmn.cpp @@ -269,63 +269,12 @@ wxString wxStaticTextBase::EscapeMarkup(const wxString& text) 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("...") -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(this)); - dc.SetFont(GetFont()); - wxArrayInt charOffsets; wxString ret; @@ -333,7 +282,7 @@ wxString wxStaticTextBase::Ellipsize(const wxString& label) const int replacementWidth = dc.GetTextExtent(wxELLIPSE_REPLACEMENT).GetWidth(); int marginWidth = dc.GetCharWidth()*2; - // handle correctly labels with newlines + // NB: we must handle correctly labels with newlines: wxString curLine; wxSize reqsize; size_t len; @@ -348,17 +297,17 @@ wxString wxStaticTextBase::Ellipsize(const wxString& label) const wxASSERT(charOffsets.GetCount() == len); size_t totalWidth = charOffsets.Last(); - if ( totalWidth > (size_t)sz.GetWidth() ) + if ( totalWidth > (size_t)maxFinalWidth ) { // we need to ellipsize this row - int excessPixels = totalWidth - sz.GetWidth() + + int excessPixels = totalWidth - maxFinalWidth + replacementWidth + marginWidth; // security margin (NEEDED!) // remove characters in excess size_t initialChar, // index of first char to erase nChars; // how many chars do we need to erase? - if (HasFlag(wxST_ELLIPSIZE_START)) + if (mode == wxST_ELLIPSIZE_START) { initialChar = 0; for (nChars=0; @@ -366,7 +315,7 @@ wxString wxStaticTextBase::Ellipsize(const wxString& label) const nChars++) ; } - else if (HasFlag(wxST_ELLIPSIZE_MIDDLE)) + else if (mode == wxST_ELLIPSIZE_MIDDLE) { // the start & end of the removed span of chars initialChar = len/2; @@ -410,13 +359,13 @@ wxString wxStaticTextBase::Ellipsize(const wxString& label) const } else { - wxASSERT(HasFlag(wxST_ELLIPSIZE_END)); + wxASSERT(mode == wxST_ELLIPSIZE_END); wxASSERT(len > 0); int maxWidth = totalWidth - excessPixels; - for (initialChar=0; - initialChar < len && - charOffsets[initialChar] < maxWidth; + for (initialChar=0; + initialChar < len && + charOffsets[initialChar] < maxWidth; initialChar++) ; @@ -426,7 +375,7 @@ wxString wxStaticTextBase::Ellipsize(const wxString& label) const } else { - initialChar--; // go back one character + initialChar--; // go back one character nChars = len - initialChar; } } @@ -442,13 +391,13 @@ wxString wxStaticTextBase::Ellipsize(const wxString& label) const curLine.erase(initialChar, nChars+1); // if there is space for the replacement dots, add them - if (sz.GetWidth() > replacementWidth) + if (maxFinalWidth > replacementWidth) curLine.insert(initialChar, wxELLIPSE_REPLACEMENT); } // if everything was ok, we should have shortened this line - // enough to make it fit in sz.GetWidth(): - wxASSERT(dc.GetTextExtent(curLine).GetWidth() < sz.GetWidth()); + // enough to make it fit in sz.maxFinalWidth: + 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(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 -- 2.47.2