From 5c87527c5a81eda63e7ccbda2f226ca02716e7da Mon Sep 17 00:00:00 2001 From: Francesco Montorsi Date: Sun, 28 Dec 2008 21:16:00 +0000 Subject: [PATCH] move Ellipsize() to wxControl so it can be easily used by other controls git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57625 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/control.h | 11 +++ include/wx/stattext.h | 16 +--- interface/wx/control.h | 28 ++++++ interface/wx/stattext.h | 48 ++-------- src/common/ctrlcmn.cpp | 168 +++++++++++++++++++++++++++++++++++ src/common/stattextcmn.cpp | 177 +------------------------------------ 6 files changed, 222 insertions(+), 226 deletions(-) diff --git a/include/wx/control.h b/include/wx/control.h index a7c6496e72..2bf0c472ad 100644 --- a/include/wx/control.h +++ b/include/wx/control.h @@ -24,6 +24,13 @@ extern WXDLLIMPEXP_DATA_CORE(const char) wxControlNameStr[]; +enum wxEllipsizeMode +{ + wxELLIPSIZE_START, + wxELLIPSIZE_MIDDLE, + wxELLIPSIZE_END +}; + // ---------------------------------------------------------------------------- // wxControl is the base class for all controls // ---------------------------------------------------------------------------- @@ -67,6 +74,10 @@ public: // static utilities: + // replaces parts of the string with ellipsis if needed + static wxString Ellipsize(const wxString& label, const wxDC& dc, + wxEllipsizeMode mode, int maxWidth); + // get the string without mnemonic characters ('&') static wxString GetLabelText(const wxString& label); diff --git a/include/wx/stattext.h b/include/wx/stattext.h index 69cee4fc97..73c1c93fc5 100644 --- a/include/wx/stattext.h +++ b/include/wx/stattext.h @@ -23,15 +23,9 @@ */ #define wxST_NO_AUTORESIZE 0x0001 #define wxST_MARKUP 0x0002 - -// 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 -}; +#define wxST_ELLIPSIZE_START 0x0004 +#define wxST_ELLIPSIZE_MIDDLE 0x0008 +#define wxST_ELLIPSIZE_END 0x0010 extern WXDLLIMPEXP_DATA_CORE(const char) wxStaticTextNameStr[]; @@ -73,10 +67,6 @@ public: // 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 // choose the default border for this window diff --git a/interface/wx/control.h b/interface/wx/control.h index 837c91521d..a0a9fab111 100644 --- a/interface/wx/control.h +++ b/interface/wx/control.h @@ -6,6 +6,17 @@ // Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// +/** + The different ellipsization modes supported by the + wxControl::Ellipsize function. +*/ +enum wxEllipsizeMode +{ + wxELLIPSIZE_START, + wxELLIPSIZE_MIDDLE, + wxELLIPSIZE_END +}; + /** @class wxControl @@ -29,6 +40,23 @@ public: */ virtual void Command(wxCommandEvent& event); + /** + 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 control's text. diff --git a/interface/wx/stattext.h b/interface/wx/stattext.h index aa5097f25b..c5ebe78294 100644 --- a/interface/wx/stattext.h +++ b/interface/wx/stattext.h @@ -6,21 +6,6 @@ // 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 @@ -30,29 +15,29 @@ enum wxEllipsizeMode @beginStyleTable @style{wxALIGN_LEFT} - Align the text to the left + Align the text to the left. @style{wxALIGN_RIGHT} - Align the text to the right + Align the text to the right. @style{wxALIGN_CENTRE} - Center the text (horizontally) + Center the text (horizontally). @style{wxST_NO_AUTORESIZE} By default, the control will adjust its size to exactly fit to the size of the text when SetLabel is called. If this style flag is given, the control will not change its size (this style is especially useful with controls which also have wxALIGN_RIGHT or 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} If the labeltext width exceeds the control width, replace the beginning - of the label with an ellipsis + of the label with an ellipsis; uses wxControl::Ellipsize. @style{wxST_ELLIPSIZE_MIDDLE} If the label text width exceeds the control width, replace the middle - of the label with an ellipsis + of the label with an ellipsis; uses wxControl::Ellipsize. @style{wxST_ELLIPSIZE_END} If the label text width exceeds the control width, replace the end - of the label with an ellipsis + of the label with an ellipsis; uses wxControl::Ellipsize. @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} @@ -111,23 +96,6 @@ public: */ 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. diff --git a/src/common/ctrlcmn.cpp b/src/common/ctrlcmn.cpp index 1ded2306b5..9928f77c29 100644 --- a/src/common/ctrlcmn.cpp +++ b/src/common/ctrlcmn.cpp @@ -203,6 +203,174 @@ int wxControlBase::FindAccelIndex(const wxString& label, wxString *labelOnly) return indexAccel; } +#define wxELLIPSE_REPLACEMENT wxT("...") + +/* static */ +wxString wxControlBase::Ellipsize(const wxString& label, const wxDC& dc, + wxEllipsizeMode mode, int maxFinalWidth) +{ + wxArrayInt charOffsets; + wxString ret; + + // these cannot be cached as they can change because of e.g. a font change + int replacementWidth = dc.GetTextExtent(wxELLIPSE_REPLACEMENT).GetWidth(); + int marginWidth = dc.GetCharWidth()*2; + + // NB: we must handle correctly labels with newlines: + wxString curLine; + wxSize reqsize; + size_t len; + for ( wxString::const_iterator pc = label.begin(); ; ++pc ) + { + if ( pc == label.end() || *pc == _T('\n') ) + { + len = curLine.length(); + if (len > 0 && + dc.GetPartialTextExtents(curLine, charOffsets)) + { + wxASSERT(charOffsets.GetCount() == len); + + size_t totalWidth = charOffsets.Last(); + if ( totalWidth > (size_t)maxFinalWidth ) + { + // we need to ellipsize this row + 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 (mode == wxST_ELLIPSIZE_START) + { + initialChar = 0; + for (nChars=0; + nChars < len && charOffsets[nChars] < excessPixels; + nChars++) + ; + } + else if (mode == wxST_ELLIPSIZE_MIDDLE) + { + // the start & end of the removed span of chars + initialChar = len/2; + size_t endChar = len/2; + + int removed = 0; + for ( ; removed < excessPixels; ) + { + if (initialChar > 0) + { + // width of the initialChar-th character + int width = charOffsets[initialChar] - + charOffsets[initialChar-1]; + + // remove the initialChar-th character + removed += width; + initialChar--; + } + + if (endChar < len - 1 && + removed < excessPixels) + { + // width of the (endChar+1)-th character + int width = charOffsets[endChar+1] - + charOffsets[endChar]; + + // remove the endChar-th character + removed += width; + endChar++; + } + + if (initialChar == 0 && endChar == len-1) + { + nChars = len+1; + break; + } + } + + initialChar++; + nChars = endChar - initialChar + 1; + } + else + { + wxASSERT(mode == wxST_ELLIPSIZE_END); + wxASSERT(len > 0); + + int maxWidth = totalWidth - excessPixels; + for (initialChar=0; + initialChar < len && + charOffsets[initialChar] < maxWidth; + initialChar++) + ; + + if (initialChar == 0) + { + nChars = len; + } + else + { + initialChar--; // go back one character + nChars = len - initialChar; + } + } + + if (nChars > len) + { + // need to remove the entire row! + curLine.clear(); + } + else + { + // erase nChars characters after initialChar (included): + curLine.erase(initialChar, nChars+1); + + // if there is space for the replacement dots, add them + 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.maxFinalWidth: + wxASSERT(dc.GetTextExtent(curLine).GetWidth() < maxFinalWidth); + } + } + + // add this (ellipsized) row to the rest of the label + ret << curLine; + if ( pc == label.end() ) + { + return ret; + } + else + { + ret << *pc; + curLine.clear(); + } + } + // we need to remove mnemonics from the label for correct calculations + else if ( *pc == _T('&') ) + { + // pc+1 is safe: at worst we'll be at end() + wxString::const_iterator next = pc + 1; + if ( next != label.end() && *next == _T('&') ) + curLine += _T('&'); // && becomes & + //else: remove this ampersand + } + // we need also to expand tabs to properly calc their size + else if ( *pc == _T('\t') ) + { + // Windows natively expands the TABs to 6 spaces. Do the same: + curLine += wxT(" "); + } + else + { + curLine += *pc; + } + } + + return ret; +} + wxBorder wxControlBase::GetDefaultBorder() const { return wxBORDER_THEME; diff --git a/src/common/stattextcmn.cpp b/src/common/stattextcmn.cpp index 33992dc246..8dce7bed74 100644 --- a/src/common/stattextcmn.cpp +++ b/src/common/stattextcmn.cpp @@ -269,175 +269,6 @@ wxString wxStaticTextBase::EscapeMarkup(const wxString& text) return ret; } -#define wxELLIPSE_REPLACEMENT wxT("...") - -/* static */ -wxString wxStaticTextBase::Ellipsize(const wxString& label, const wxDC& dc, - wxEllipsizeMode mode, int maxFinalWidth) -{ - wxArrayInt charOffsets; - wxString ret; - - // these cannot be cached as they can change because of e.g. a font change - int replacementWidth = dc.GetTextExtent(wxELLIPSE_REPLACEMENT).GetWidth(); - int marginWidth = dc.GetCharWidth()*2; - - // NB: we must handle correctly labels with newlines: - wxString curLine; - wxSize reqsize; - size_t len; - for ( wxString::const_iterator pc = label.begin(); ; ++pc ) - { - if ( pc == label.end() || *pc == _T('\n') ) - { - len = curLine.length(); - if (len > 0 && - dc.GetPartialTextExtents(curLine, charOffsets)) - { - wxASSERT(charOffsets.GetCount() == len); - - size_t totalWidth = charOffsets.Last(); - if ( totalWidth > (size_t)maxFinalWidth ) - { - // we need to ellipsize this row - 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 (mode == wxST_ELLIPSIZE_START) - { - initialChar = 0; - for (nChars=0; - nChars < len && charOffsets[nChars] < excessPixels; - nChars++) - ; - } - else if (mode == wxST_ELLIPSIZE_MIDDLE) - { - // the start & end of the removed span of chars - initialChar = len/2; - size_t endChar = len/2; - - int removed = 0; - for ( ; removed < excessPixels; ) - { - if (initialChar > 0) - { - // width of the initialChar-th character - int width = charOffsets[initialChar] - - charOffsets[initialChar-1]; - - // remove the initialChar-th character - removed += width; - initialChar--; - } - - if (endChar < len - 1 && - removed < excessPixels) - { - // width of the (endChar+1)-th character - int width = charOffsets[endChar+1] - - charOffsets[endChar]; - - // remove the endChar-th character - removed += width; - endChar++; - } - - if (initialChar == 0 && endChar == len-1) - { - nChars = len+1; - break; - } - } - - initialChar++; - nChars = endChar - initialChar + 1; - } - else - { - wxASSERT(mode == wxST_ELLIPSIZE_END); - wxASSERT(len > 0); - - int maxWidth = totalWidth - excessPixels; - for (initialChar=0; - initialChar < len && - charOffsets[initialChar] < maxWidth; - initialChar++) - ; - - if (initialChar == 0) - { - nChars = len; - } - else - { - initialChar--; // go back one character - nChars = len - initialChar; - } - } - - if (nChars > len) - { - // need to remove the entire row! - curLine.clear(); - } - else - { - // erase nChars characters after initialChar (included): - curLine.erase(initialChar, nChars+1); - - // if there is space for the replacement dots, add them - 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.maxFinalWidth: - wxASSERT(dc.GetTextExtent(curLine).GetWidth() < maxFinalWidth); - } - } - - // add this (ellipsized) row to the rest of the label - ret << curLine; - if ( pc == label.end() ) - { - return ret; - } - else - { - ret << *pc; - curLine.clear(); - } - } - // we need to remove mnemonics from the label for correct calculations - else if ( *pc == _T('&') ) - { - // pc+1 is safe: at worst we'll be at end() - wxString::const_iterator next = pc + 1; - if ( next != label.end() && *next == _T('&') ) - curLine += _T('&'); // && becomes & - //else: remove this ampersand - } - // we need also to expand tabs to properly calc their size - else if ( *pc == _T('\t') ) - { - // Windows natively expands the TABs to 6 spaces. Do the same: - curLine += wxT(" "); - } - else - { - curLine += *pc; - } - } - - return ret; -} - - // ---------------------------------------------------------------------------- // wxStaticTextBase - generic implementation for wxST_ELLIPSIZE_* support @@ -493,11 +324,11 @@ wxString wxStaticTextBase::Ellipsize(const wxString& label) const 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; + if (HasFlag(wxST_ELLIPSIZE_START)) mode = wxELLIPSIZE_START; + else if (HasFlag(wxST_ELLIPSIZE_MIDDLE)) mode = wxELLIPSIZE_MIDDLE; + else if (HasFlag(wxST_ELLIPSIZE_END)) mode = wxELLIPSIZE_END; - return Ellipsize(label, dc, mode, sz.GetWidth()); + return wxControl::Ellipsize(label, dc, mode, sz.GetWidth()); } #endif // wxUSE_STATTEXT -- 2.45.2