extern WXDLLIMPEXP_DATA_CORE(const char) wxControlNameStr[];
+
+// ----------------------------------------------------------------------------
+// Ellipsize() constants
+// ----------------------------------------------------------------------------
+
+enum wxEllipsizeFlags
+{
+ wxELLIPSIZE_PROCESS_MNEMONICS = 1,
+ wxELLIPSIZE_EXPAND_TAB = 2,
+
+ wxELLIPSIZE_DEFAULT_FLAGS = wxELLIPSIZE_PROCESS_MNEMONICS|wxELLIPSIZE_EXPAND_TAB
+};
+
enum wxEllipsizeMode
{
wxELLIPSIZE_START,
SetLabel(EscapeMnemonics(text));
}
- // 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);
-
- // removes the mnemonics characters
- static wxString RemoveMnemonics(const wxString& str);
-
- // escapes (by doubling them) the mnemonics
- static wxString EscapeMnemonics(const wxString& str);
-
- // return the accel index in the string or -1 if none and puts the modified
- // string into second parameter if non NULL
- static int FindAccelIndex(const wxString& label,
- wxString *labelOnly = NULL);
-
-
// controls by default inherit the colours of their parents, if a
// particular control class doesn't want to do it, it can override
// ShouldInheritColours() to return false
// wxControl-specific processing after processing the update event
virtual void DoUpdateWindowUI(wxUpdateUIEvent& event);
+
+
+ // static utilities
+ // ----------------
+
+ // replaces parts of the (multiline) string with ellipsis if needed
+ static wxString Ellipsize(const wxString& label, const wxDC& dc,
+ wxEllipsizeMode mode, int maxWidth,
+ int flags = wxELLIPSIZE_DEFAULT_FLAGS);
+
+ // get the string without mnemonic characters ('&')
+ static wxString GetLabelText(const wxString& label);
+
+ // removes the mnemonics characters
+ static wxString RemoveMnemonics(const wxString& str);
+
+ // escapes (by doubling them) the mnemonics
+ static wxString EscapeMnemonics(const wxString& str);
+
+ // return the accel index in the string or -1 if none and puts the modified
+ // string into second parameter if non NULL
+ static int FindAccelIndex(const wxString& label,
+ wxString *labelOnly = NULL);
+
protected:
// choose the default border for this window
virtual wxBorder GetDefaultBorder() const;
// initialize the common fields of wxCommandEvent
void InitCommandEvent(wxCommandEvent& event) const;
+ // Ellipsize() helper:
+ static wxString DoEllipsizeSingleLine(const wxString& label, const wxDC& dc,
+ wxEllipsizeMode mode, int maxWidth,
+ int replacementWidth, int marginWidth);
+
// this field contains the label in wx format, i.e. with '&' mnemonics
wxString m_labelOrig;
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
+/**
+ Flags used by wxControl::Ellipsize function.
+*/
+enum wxEllipsizeFlags
+{
+ /// With this flag when calculating the size of the passed string, mnemonics
+ /// characters (see wxControl::SetLabel) will be automatically reduced to a
+ /// single character.
+ /// This leads to correct calculations only if the string passed to Ellipsize()
+ /// will be used with wxControl::SetLabel. If you don't want ampersand to
+ /// be interpreted as mnemonics (e.g. because you use wxControl::SetLabelText)
+ /// then don't use this flag.
+ wxELLIPSIZE_PROCESS_MNEMONICS = 1,
+
+ /// This flag tells wxControl::Ellipsize to calculate the width of tab
+ /// characters @c '\\t' as 6 spaces.
+ wxELLIPSIZE_EXPAND_TAB = 2,
+
+ /// The default flags for wxControl::Ellipsize.
+ wxELLIPSIZE_DEFAULT_FLAGS = wxELLIPSIZE_PROCESS_MNEMONICS|wxELLIPSIZE_EXPAND_TAB
+};
+
+
/**
The different ellipsization modes supported by the
wxControl::Ellipsize function.
*/
enum wxEllipsizeMode
{
+ /// Put the ellipsis at the start of the string, if the string needs ellipsization.
wxELLIPSIZE_START,
+
+ /// Put the ellipsis in the middle of the string, if the string needs ellipsization.
wxELLIPSIZE_MIDDLE,
+
+ /// Put the ellipsis at the end of the string, if the string needs ellipsization.
wxELLIPSIZE_END
};
The ellipsization modes. See ::wxEllipsizeMode.
@param maxWidth
The maximum width of the returned string in pixels.
+ @param flags
+ One or more of the ::wxEllipsize
*/
static wxString Ellipsize(const wxString& label, const wxDC& dc,
- wxEllipsizeMode mode, int maxWidth);
+ wxEllipsizeMode mode, int maxWidth,
+ int flags = wxELLIPSIZE_DEFAULT_FLAGS);
/**
Returns the control's text.
return indexAccel;
}
+wxBorder wxControlBase::GetDefaultBorder() const
+{
+ return wxBORDER_THEME;
+}
+
+// ----------------------------------------------------------------------------
+// wxControlBase - ellipsization code
+// ----------------------------------------------------------------------------
+
#define wxELLIPSE_REPLACEMENT wxT("...")
+/* static and protected */
+wxString wxControlBase::DoEllipsizeSingleLine(const wxString& curLine, const wxDC& dc,
+ wxEllipsizeMode mode, int maxFinalWidth,
+ int replacementWidth, int marginWidth)
+{
+ wxASSERT_MSG(replacementWidth > 0 && marginWidth > 0,
+ "Invalid parameters");
+ wxASSERT_MSG(!curLine.Contains('\n'),
+ "Use Ellipsize() instead!");
+
+ // NOTE: this function assumes that any mnemonic/tab character has already
+ // been handled if it was necessary to handle them (see Ellipsize())
+
+ if (maxFinalWidth <= 0)
+ return wxEmptyString;
+
+ wxArrayInt charOffsets;
+ size_t len = curLine.length();
+ if (len == 0 ||
+ !dc.GetPartialTextExtents(curLine, charOffsets))
+ return curLine;
+
+ wxASSERT(charOffsets.GetCount() == len);
+
+ size_t totalWidth = charOffsets.Last();
+ if ( totalWidth <= (size_t)maxFinalWidth )
+ return curLine; // we don't need to do any ellipsization!
+
+ 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?
+
+ switch (mode)
+ {
+ case wxELLIPSIZE_START:
+ initialChar = 0;
+ for (nChars=0;
+ nChars < len && charOffsets[nChars] < excessPixels;
+ nChars++)
+ ;
+ break;
+
+ case wxELLIPSIZE_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;
+ }
+ break;
+
+ case wxELLIPSIZE_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;
+ }
+ }
+ break;
+
+ default:
+ wxFAIL_MSG("invalid ellipsize mode");
+ }
+
+ wxString ret(curLine);
+ if (nChars >= len)
+ {
+ // need to remove the entire row!
+ ret.clear();
+ }
+ else
+ {
+ // erase nChars characters after initialChar (included):
+ ret.erase(initialChar, nChars+1);
+
+ // if there is space for the replacement dots, add them
+ if (maxFinalWidth > replacementWidth)
+ ret.append(wxELLIPSE_REPLACEMENT);//.insert(initialChar, wxELLIPSE_REPLACEMENT);
+ }
+
+ // if everything was ok, we should have shortened this line
+ // enough to make it fit in maxFinalWidth:
+ wxASSERT(dc.GetTextExtent(ret).GetWidth() < maxFinalWidth);
+
+ return ret;
+}
+
/* static */
wxString wxControlBase::Ellipsize(const wxString& label, const wxDC& dc,
- wxEllipsizeMode mode, int maxFinalWidth)
+ wxEllipsizeMode mode, int maxFinalWidth,
+ int flags)
{
- wxArrayInt charOffsets;
wxString ret;
- // these cannot be cached as they can change because of e.g. a font change
+ // these cannot be cached between different Ellipsize() calls as they can
+ // change because of e.g. a font change; however we calculate them only once
+ // when ellipsizing multiline labels:
int replacementWidth = dc.GetTextExtent(wxELLIPSE_REPLACEMENT).GetWidth();
- int marginWidth = dc.GetCharWidth()*2;
+ int marginWidth = dc.GetCharWidth();
// 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') )
+ if ( pc == label.end() || *pc == wxS('\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 == wxELLIPSIZE_START)
- {
- initialChar = 0;
- for (nChars=0;
- nChars < len && charOffsets[nChars] < excessPixels;
- nChars++)
- ;
- }
- else if (mode == wxELLIPSIZE_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 == wxELLIPSIZE_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 maxFinalWidth:
- wxASSERT(dc.GetTextExtent(curLine).GetWidth() < maxFinalWidth);
- }
- }
+ curLine = DoEllipsizeSingleLine(curLine, dc, mode, maxFinalWidth,
+ replacementWidth, marginWidth);
// add this (ellipsized) row to the rest of the label
ret << curLine;
}
}
// we need to remove mnemonics from the label for correct calculations
- else if ( *pc == _T('&') )
+ else if ( *pc == wxS('&') && (flags & wxELLIPSIZE_PROCESS_MNEMONICS) != 0 )
{
// 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 &
+ 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 == _T('\t') )
+ else if ( *pc == wxS('\t') && (flags & wxELLIPSIZE_EXPAND_TAB) != 0 )
{
// Windows natively expands the TABs to 6 spaces. Do the same:
- curLine += wxT(" ");
+ curLine += wxS(" ");
}
else
{
//return ret;
}
-wxBorder wxControlBase::GetDefaultBorder() const
-{
- return wxBORDER_THEME;
-}
// ----------------------------------------------------------------------------