Fixed tab selection bug

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
This commit is contained in:
Julian Smart 2006-10-13 14:30:40 +00:00
parent 9654efd332
commit cfa3b25626
2 changed files with 137 additions and 56 deletions

View File

@ -1205,9 +1205,21 @@ public:
/// Get combined attributes of the base style and paragraph style. /// Get combined attributes of the base style and paragraph style.
wxTextAttrEx GetCombinedAttributes() const; 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: protected:
/// The lines that make up the wrapped paragraph /// The lines that make up the wrapped paragraph
wxRichTextLineList m_cachedLines; wxRichTextLineList m_cachedLines;
/// Default tabstops
static wxArrayInt sm_defaultTabs;
}; };
/*! /*!

View File

@ -2433,6 +2433,8 @@ bool wxRichTextParagraphLayoutBox::ApplyStyleSheet(wxRichTextStyleSheet* styleSh
IMPLEMENT_DYNAMIC_CLASS(wxRichTextParagraph, wxRichTextBox) IMPLEMENT_DYNAMIC_CLASS(wxRichTextParagraph, wxRichTextBox)
wxArrayInt wxRichTextParagraph::sm_defaultTabs;
wxRichTextParagraph::wxRichTextParagraph(wxRichTextObject* parent, wxTextAttrEx* style): wxRichTextParagraph::wxRichTextParagraph(wxRichTextObject* parent, wxTextAttrEx* style):
wxRichTextBox(parent) wxRichTextBox(parent)
{ {
@ -3482,6 +3484,23 @@ wxTextAttrEx wxRichTextParagraph::GetCombinedAttributes() const
return attr; 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 * wxRichTextLine
* This object represents a line in a paragraph, and stores * This object represents a line in a paragraph, and stores
@ -3542,6 +3561,8 @@ wxRichTextPlainText::wxRichTextPlainText(const wxString& text, wxRichTextObject*
m_text = text; m_text = text;
} }
#define USE_KERNING_FIX 1
/// Draw the item /// Draw the item
bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int descent, int WXUNUSED(style)) 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); wxString stringFragment = m_text.Mid(r1 - offset, fragmentLen);
DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, false); 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. // 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); wxString stringFragment = m_text.Mid(s1 - offset, fragmentLen);
DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, true); 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 // 3. Remaining unselected chunk, if any
@ -3635,26 +3690,30 @@ 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) bool wxRichTextPlainText::DrawTabbedString(wxDC& dc, const wxTextAttrEx& attr, const wxRect& rect,wxString& str, wxCoord& x, wxCoord& y, bool selected)
{ {
wxArrayInt tab_array = attr.GetTabs(); bool hasTabs = (str.Find(wxT('\t')) != wxNOT_FOUND);
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();
for (int i = 0; i < num_tabs; ++i)
{
tab_array[i] = dc.LogicalToDeviceXRel(tab_array[i]);
}
dc.SetMapMode(map_mode ); wxArrayInt tabArray;
int next_tab_pos = -1; int tabCount;
int tab_pos = -1; if (hasTabs)
{
if (attr.GetTabs().IsEmpty())
tabArray = wxRichTextParagraph::GetDefaultTabs();
else
tabArray = attr.GetTabs();
tabCount = tabArray.GetCount();
for (int i = 0; i < tabCount; ++i)
{
int pos = tabArray[i];
pos = ConvertTenthsMMToPixels(dc, pos);
tabArray[i] = pos;
}
}
else
tabCount = 0;
int nextTabPos = -1;
int tabPos = -1;
wxCoord w, h; wxCoord w, h;
if (selected) if (selected)
@ -3670,33 +3729,36 @@ bool wxRichTextPlainText::DrawTabbedString(wxDC& dc, const wxTextAttrEx& attr, c
dc.SetBackgroundMode(wxTRANSPARENT); dc.SetBackgroundMode(wxTRANSPARENT);
} }
while (str.Find(wxT('\t')) >= 0) while (hasTabs)
{ {
// the string has a tab // the string has a tab
// break up the string at the Tab // break up the string at the Tab
wxString stringChunk = str.BeforeFirst(wxT('\t')); wxString stringChunk = str.BeforeFirst(wxT('\t'));
str = str.AfterFirst(wxT('\t')); str = str.AfterFirst(wxT('\t'));
dc.GetTextExtent(stringChunk, & w, & h); dc.GetTextExtent(stringChunk, & w, & h);
tab_pos = x + w; tabPos = x + w;
bool not_found = true; 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); nextTabPos = tabArray.Item(i);
if (next_tab_pos > tab_pos) if (nextTabPos > tabPos)
{ {
not_found = false; not_found = false;
if (selected) if (selected)
{ {
w = next_tab_pos - x; w = nextTabPos - x;
wxRect selRect(x, rect.y, w, rect.GetHeight()); wxRect selRect(x, rect.y, w, rect.GetHeight());
dc.DrawRectangle(selRect); dc.DrawRectangle(selRect);
} }
dc.DrawText(stringChunk, x, y); dc.DrawText(stringChunk, x, y);
x = next_tab_pos; x = nextTabPos;
} }
} }
hasTabs = (str.Find(wxT('\t')) != wxNOT_FOUND);
} }
if (!str.IsEmpty())
{
dc.GetTextExtent(str, & w, & h); dc.GetTextExtent(str, & w, & h);
if (selected) if (selected)
{ {
@ -3705,6 +3767,7 @@ bool wxRichTextPlainText::DrawTabbedString(wxDC& dc, const wxTextAttrEx& attr, c
} }
dc.DrawText(str, x, y); dc.DrawText(str, x, y);
x += w; x += w;
}
return true; return true;
} }
@ -3767,29 +3830,25 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz
wxString stringChunk = m_text.Mid(startPos, (size_t) len); wxString stringChunk = m_text.Mid(startPos, (size_t) len);
wxCoord w, h; wxCoord w, h;
int width = 0; int width = 0;
if (stringChunk.Find(wxT('\t')) >= 0) if (stringChunk.Find(wxT('\t')) != wxNOT_FOUND)
{ {
// the string has a tab // the string has a tab
wxArrayInt tab_array = textAttr.GetTabs(); wxArrayInt tabArray;
if (tab_array.IsEmpty()) if (textAttr.GetTabs().IsEmpty())
tabArray = wxRichTextParagraph::GetDefaultTabs();
else
tabArray = textAttr.GetTabs();
int tabCount = tabArray.GetCount();
for (int i = 0; i < tabCount; ++i)
{ {
// create a default tab list at 10 mm each. int pos = tabArray[i];
for (int i = 0; i < 20; ++i) pos = ((wxRichTextPlainText*) this)->ConvertTenthsMMToPixels(dc, pos);
{ tabArray[i] = pos;
tab_array.Add(i*100);
}
} }
int map_mode = dc.GetMapMode(); int nextTabPos = -1;
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]);
}
dc.SetMapMode(map_mode );
int next_tab_pos = -1;
while (stringChunk.Find(wxT('\t')) >= 0) while (stringChunk.Find(wxT('\t')) >= 0)
{ {
@ -3799,15 +3858,15 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz
stringChunk = stringChunk.AfterFirst(wxT('\t')); stringChunk = stringChunk.AfterFirst(wxT('\t'));
dc.GetTextExtent(stringFragment, & w, & h); dc.GetTextExtent(stringFragment, & w, & h);
width += w; width += w;
int absolute_width = width + position.x; int absoluteWidth = width + position.x;
bool not_found = true; bool notFound = true;
for (int i = 0; i < num_tabs && not_found; ++i) for (int i = 0; i < tabCount && notFound; ++i)
{ {
next_tab_pos = tab_array.Item(i); nextTabPos = tabArray.Item(i);
if (next_tab_pos > absolute_width) if (nextTabPos > absoluteWidth)
{ {
not_found = false; notFound = false;
width = next_tab_pos - position.x; width = nextTabPos - position.x;
} }
} }
} }
@ -4858,8 +4917,18 @@ class wxRichTextModule: public wxModule
DECLARE_DYNAMIC_CLASS(wxRichTextModule) DECLARE_DYNAMIC_CLASS(wxRichTextModule)
public: public:
wxRichTextModule() {} wxRichTextModule() {}
bool OnInit() { wxRichTextBuffer::InitStandardHandlers(); return true; }; bool OnInit()
void OnExit() { wxRichTextBuffer::CleanUpHandlers(); wxRichTextDecimalToRoman(-1); }; {
wxRichTextBuffer::InitStandardHandlers();
wxRichTextParagraph::InitDefaultTabs();
return true;
};
void OnExit()
{
wxRichTextBuffer::CleanUpHandlers();
wxRichTextDecimalToRoman(-1);
wxRichTextParagraph::ClearDefaultTabs();
};
}; };
IMPLEMENT_DYNAMIC_CLASS(wxRichTextModule, wxModule) IMPLEMENT_DYNAMIC_CLASS(wxRichTextModule, wxModule)