]> git.saurik.com Git - wxWidgets.git/commitdiff
split wxControl::Ellipsize() in two functions for better readability of the code...
authorFrancesco Montorsi <f18m_cpp217828@yahoo.it>
Sun, 8 Feb 2009 12:56:14 +0000 (12:56 +0000)
committerFrancesco Montorsi <f18m_cpp217828@yahoo.it>
Sun, 8 Feb 2009 12:56:14 +0000 (12:56 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@58759 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/control.h
interface/wx/control.h
src/common/ctrlcmn.cpp

index eaa6221123fb5ef8178ee833824f19b60d828de8..5427a2d4aaabe2134675a1af07128be4f52b9996 100644 (file)
 
 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,
@@ -77,27 +90,6 @@ public:
         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
@@ -115,6 +107,30 @@ public:
     // 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;
@@ -132,6 +148,11 @@ protected:
     // 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;
 
index 68f220590fdb4c1e0de5c350553f3b9482ba8eba..cba493cbb97d60d04fd8a83c147d32564a67ea84 100644 (file)
@@ -6,14 +6,42 @@
 // 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
 };
 
@@ -53,9 +81,12 @@ public:
             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.
index 8cb01a3adb253be0c0b5fdc94ad2a85257e01f6d..3b32359f668223c26b6a322669c4d4d254c96dc9 100644 (file)
@@ -212,137 +212,178 @@ int wxControlBase::FindAccelIndex(const wxString& label, wxString *labelOnly)
     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;
@@ -358,19 +399,19 @@ wxString wxControlBase::Ellipsize(const wxString& label, const wxDC& dc,
             }
         }
         // 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
         {
@@ -384,10 +425,6 @@ wxString wxControlBase::Ellipsize(const wxString& label, const wxDC& dc,
     //return ret;
 }
 
-wxBorder wxControlBase::GetDefaultBorder() const
-{
-    return wxBORDER_THEME;
-}
 
 
 // ----------------------------------------------------------------------------