]> git.saurik.com Git - wxWidgets.git/commitdiff
Fixed tab selection bug
authorJulian Smart <julian@anthemion.co.uk>
Fri, 13 Oct 2006 14:30:40 +0000 (14:30 +0000)
committerJulian Smart <julian@anthemion.co.uk>
Fri, 13 Oct 2006 14:30:40 +0000 (14:30 +0000)
Slight improvement to kerning-related jumpy text when selecting
Default tab efficiency improvement and naming conventions cleanup

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41987 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/richtext/richtextbuffer.h
src/richtext/richtextbuffer.cpp

index a2c3fb982c1716c0bc27039d302b39646866ff7a..557e5b46ca14d45f9c18f273b8e7979e12203a89 100644 (file)
@@ -1205,9 +1205,21 @@ public:
     /// Get combined attributes of the base style and paragraph style.
     wxTextAttrEx GetCombinedAttributes() const;
 
+    /// Create default tabstop array
+    static void InitDefaultTabs();
+
+    /// Clear default tabstop array
+    static void ClearDefaultTabs();
+
+    /// Get default tabstop array
+    static const wxArrayInt& GetDefaultTabs() { return sm_defaultTabs; }
+
 protected:
     /// The lines that make up the wrapped paragraph
     wxRichTextLineList m_cachedLines;
+
+    /// Default tabstops
+    static wxArrayInt  sm_defaultTabs;
 };
 
 /*!
index 20d4cbef7f2f22aab2cf0626e3578f3211f068f3..0921ba0ff1a6007f22d410a54d970ba7ff925123 100644 (file)
@@ -2433,6 +2433,8 @@ bool wxRichTextParagraphLayoutBox::ApplyStyleSheet(wxRichTextStyleSheet* styleSh
 
 IMPLEMENT_DYNAMIC_CLASS(wxRichTextParagraph, wxRichTextBox)
 
+wxArrayInt wxRichTextParagraph::sm_defaultTabs;
+
 wxRichTextParagraph::wxRichTextParagraph(wxRichTextObject* parent, wxTextAttrEx* style):
     wxRichTextBox(parent)
 {
@@ -3482,6 +3484,23 @@ wxTextAttrEx wxRichTextParagraph::GetCombinedAttributes() const
     return attr;
 }
 
+/// Create default tabstop array
+void wxRichTextParagraph::InitDefaultTabs()
+{
+    // create a default tab list at 10 mm each.
+    for (int i = 0; i < 20; ++i)
+    {
+        sm_defaultTabs.Add(i*100);
+    }
+}
+
+/// Clear default tabstop array
+void wxRichTextParagraph::ClearDefaultTabs()
+{
+    sm_defaultTabs.Clear();
+}
+
+
 /*!
  * wxRichTextLine
  * This object represents a line in a paragraph, and stores
@@ -3542,6 +3561,8 @@ wxRichTextPlainText::wxRichTextPlainText(const wxString& text, wxRichTextObject*
     m_text = text;
 }
 
+#define USE_KERNING_FIX 1
+
 /// Draw the item
 bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int descent, int WXUNUSED(style))
 {
@@ -3599,6 +3620,23 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR
             wxString stringFragment = m_text.Mid(r1 - offset, fragmentLen);
 
             DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, false);
+
+#if USE_KERNING_FIX
+            if (stringChunk.Find(wxT("\t")) == wxNOT_FOUND)
+            {
+                // Compensate for kerning difference
+                wxString stringFragment2(m_text.Mid(r1 - offset, fragmentLen+1));
+                wxString stringFragment3(m_text.Mid(r1 - offset + fragmentLen, 1));
+                
+                wxCoord w1, h1, w2, h2, w3, h3;
+                dc.GetTextExtent(stringFragment,  & w1, & h1);
+                dc.GetTextExtent(stringFragment2, & w2, & h2);
+                dc.GetTextExtent(stringFragment3, & w3, & h3);
+                
+                int kerningDiff = (w1 + w3) - w2;
+                x = x - kerningDiff;
+            }
+#endif
         }
 
         // 2. Selected chunk, if any.
@@ -3613,6 +3651,23 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR
             wxString stringFragment = m_text.Mid(s1 - offset, fragmentLen);
 
             DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, true);
+
+#if USE_KERNING_FIX
+            if (stringChunk.Find(wxT("\t")) == wxNOT_FOUND)
+            {
+                // Compensate for kerning difference
+                wxString stringFragment2(m_text.Mid(s1 - offset, fragmentLen+1));
+                wxString stringFragment3(m_text.Mid(s1 - offset + fragmentLen, 1));
+                
+                wxCoord w1, h1, w2, h2, w3, h3;
+                dc.GetTextExtent(stringFragment,  & w1, & h1);
+                dc.GetTextExtent(stringFragment2, & w2, & h2);
+                dc.GetTextExtent(stringFragment3, & w3, & h3);
+                
+                int kerningDiff = (w1 + w3) - w2;
+                x = x - kerningDiff;
+            }
+#endif
         }
 
         // 3. Remaining unselected chunk, if any
@@ -3635,29 +3690,33 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR
 
 bool wxRichTextPlainText::DrawTabbedString(wxDC& dc, const wxTextAttrEx& attr, const wxRect& rect,wxString& str, wxCoord& x, wxCoord& y, bool selected)
 {
-    wxArrayInt tab_array =  attr.GetTabs();
-    if (tab_array.IsEmpty())
+    bool hasTabs = (str.Find(wxT('\t')) != wxNOT_FOUND);
+
+    wxArrayInt tabArray;
+    int tabCount;
+    if (hasTabs)
     {
-        // create a default tab list at 10 mm each.
-        for (int i = 0; i < 20; ++i)
+        if (attr.GetTabs().IsEmpty())
+            tabArray = wxRichTextParagraph::GetDefaultTabs();
+        else
+            tabArray = attr.GetTabs();
+        tabCount = tabArray.GetCount();
+
+        for (int i = 0; i < tabCount; ++i)
         {
-            tab_array.Add(i*100);
+            int pos = tabArray[i];
+            pos = ConvertTenthsMMToPixels(dc, pos);
+            tabArray[i] = pos;
         }
     }
-    int map_mode = dc.GetMapMode();
-    dc.SetMapMode(wxMM_LOMETRIC );
-    int num_tabs = tab_array.GetCount();
-    for (int i = 0; i < num_tabs; ++i)
-    {
-       tab_array[i] = dc.LogicalToDeviceXRel(tab_array[i]);
-    }
+    else
+        tabCount = 0;
 
-    dc.SetMapMode(map_mode );
-    int next_tab_pos = -1;
-    int tab_pos = -1;
+    int nextTabPos = -1;
+    int tabPos = -1;
     wxCoord w, h;
 
-    if(selected)
+    if (selected)
     {
         dc.SetBrush(*wxBLACK_BRUSH);
         dc.SetPen(*wxBLACK_PEN);
@@ -3670,41 +3729,45 @@ bool wxRichTextPlainText::DrawTabbedString(wxDC& dc, const wxTextAttrEx& attr, c
         dc.SetBackgroundMode(wxTRANSPARENT);
     }
 
-    while (str.Find(wxT('\t')) >= 0)
+    while (hasTabs)
     {
         // the string has a tab
         // break up the string at the Tab
         wxString stringChunk = str.BeforeFirst(wxT('\t'));
         str = str.AfterFirst(wxT('\t'));
         dc.GetTextExtent(stringChunk, & w, & h);
-        tab_pos = x + w;
+        tabPos = x + w;
         bool not_found = true;
-        for (int i = 0; i < num_tabs && not_found; ++i)
+        for (int i = 0; i < tabCount && not_found; ++i)
         {
-            next_tab_pos = tab_array.Item(i);
-            if (next_tab_pos > tab_pos)
+            nextTabPos = tabArray.Item(i);
+            if (nextTabPos > tabPos)
             {
                 not_found = false;
                 if (selected)
                 {
-                    w = next_tab_pos - x;
+                    w = nextTabPos - x;
                     wxRect selRect(x, rect.y, w, rect.GetHeight());
                     dc.DrawRectangle(selRect);
                 }
                 dc.DrawText(stringChunk, x, y);
-                x = next_tab_pos;
+                x = nextTabPos;
             }
         }
+        hasTabs = (str.Find(wxT('\t')) != wxNOT_FOUND);
     }
 
-    dc.GetTextExtent(str, & w, & h);
-    if (selected)
+    if (!str.IsEmpty())
     {
-        wxRect selRect(x, rect.y, w, rect.GetHeight());
-        dc.DrawRectangle(selRect);
+        dc.GetTextExtent(str, & w, & h);
+        if (selected)
+        {
+            wxRect selRect(x, rect.y, w, rect.GetHeight());
+            dc.DrawRectangle(selRect);
+        }
+        dc.DrawText(str, x, y);
+        x += w;
     }
-    dc.DrawText(str, x, y);
-    x += w;
     return true;
 
 }
@@ -3767,29 +3830,25 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz
     wxString stringChunk = m_text.Mid(startPos, (size_t) len);
     wxCoord w, h;
     int width = 0;
-    if (stringChunk.Find(wxT('\t')) >= 0)
+    if (stringChunk.Find(wxT('\t')) != wxNOT_FOUND)
     {
         // the string has a tab
-        wxArrayInt tab_array =  textAttr.GetTabs();
-        if (tab_array.IsEmpty())
-        {
-            // create a default tab list at 10 mm each.
-            for (int i = 0; i < 20; ++i)
-            {
-                tab_array.Add(i*100);
-            }
-        }
-
-        int map_mode = dc.GetMapMode();
-        dc.SetMapMode(wxMM_LOMETRIC );
-        int num_tabs = tab_array.GetCount();
+        wxArrayInt tabArray;
+        if (textAttr.GetTabs().IsEmpty())
+            tabArray = wxRichTextParagraph::GetDefaultTabs();
+        else
+            tabArray = textAttr.GetTabs();
 
-        for (int i = 0; i < num_tabs; ++i)
+        int tabCount = tabArray.GetCount();
+        
+        for (int i = 0; i < tabCount; ++i)
         {
-            tab_array[i] = dc.LogicalToDeviceXRel(tab_array[i]);
+            int pos = tabArray[i];
+            pos = ((wxRichTextPlainText*) this)->ConvertTenthsMMToPixels(dc, pos);
+            tabArray[i] = pos;
         }
-        dc.SetMapMode(map_mode );
-        int next_tab_pos = -1;
+        
+        int nextTabPos = -1;
 
         while (stringChunk.Find(wxT('\t')) >= 0)
         {
@@ -3799,15 +3858,15 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz
             stringChunk = stringChunk.AfterFirst(wxT('\t'));
             dc.GetTextExtent(stringFragment, & w, & h);
             width += w;
-            int absolute_width = width + position.x;
-            bool not_found = true;
-            for (int i = 0; i < num_tabs && not_found; ++i)
+            int absoluteWidth = width + position.x;
+            bool notFound = true;
+            for (int i = 0; i < tabCount && notFound; ++i)
             {
-                next_tab_pos = tab_array.Item(i);
-                if (next_tab_pos > absolute_width)
+                nextTabPos = tabArray.Item(i);
+                if (nextTabPos > absoluteWidth)
                 {
-                    not_found = false;
-                    width = next_tab_pos - position.x;
+                    notFound = false;
+                    width = nextTabPos - position.x;
                 }
             }
         }
@@ -4858,8 +4917,18 @@ class wxRichTextModule: public wxModule
 DECLARE_DYNAMIC_CLASS(wxRichTextModule)
 public:
     wxRichTextModule() {}
-    bool OnInit() { wxRichTextBuffer::InitStandardHandlers(); return true; };
-    void OnExit() { wxRichTextBuffer::CleanUpHandlers(); wxRichTextDecimalToRoman(-1); };
+    bool OnInit()
+    {
+        wxRichTextBuffer::InitStandardHandlers();
+        wxRichTextParagraph::InitDefaultTabs();
+        return true;
+    };
+    void OnExit()
+    {
+        wxRichTextBuffer::CleanUpHandlers();
+        wxRichTextDecimalToRoman(-1);
+        wxRichTextParagraph::ClearDefaultTabs();
+    };
 };
 
 IMPLEMENT_DYNAMIC_CLASS(wxRichTextModule, wxModule)