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
This commit is contained in:
Francesco Montorsi
2008-12-28 21:16:00 +00:00
parent f8f31de610
commit 5c87527c5a
6 changed files with 222 additions and 226 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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