Merge branch 'wxrichtextctrl_word_wrapping_opt' of https://github.com/mehmet-soyturk/wxWidgets
Optimize wrapping long lines in wxRichTextCtrl. See https://github.com/wxWidgets/wxWidgets/pull/2523
This commit is contained in:
@@ -4654,6 +4654,7 @@ protected:
|
|||||||
|
|
||||||
// The lines that make up the wrapped paragraph
|
// The lines that make up the wrapped paragraph
|
||||||
wxRichTextLineList m_cachedLines;
|
wxRichTextLineList m_cachedLines;
|
||||||
|
wxVector<wxRichTextLine*> m_cachedLinesVect;
|
||||||
|
|
||||||
// Whether the paragraph is impacted by floating objects from above
|
// Whether the paragraph is impacted by floating objects from above
|
||||||
int m_impactedByFloatingObjects;
|
int m_impactedByFloatingObjects;
|
||||||
|
@@ -5697,6 +5697,7 @@ void wxRichTextParagraph::Copy(const wxRichTextParagraph& obj)
|
|||||||
void wxRichTextParagraph::ClearLines()
|
void wxRichTextParagraph::ClearLines()
|
||||||
{
|
{
|
||||||
WX_CLEAR_LIST(wxRichTextLineList, m_cachedLines);
|
WX_CLEAR_LIST(wxRichTextLineList, m_cachedLines);
|
||||||
|
m_cachedLinesVect.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get/set the object size for the given range. Returns false if the range
|
/// Get/set the object size for the given range. Returns false if the range
|
||||||
@@ -6529,7 +6530,8 @@ wxRichTextLine* wxRichTextParagraph::AllocateLine(int pos)
|
|||||||
{
|
{
|
||||||
if (pos < (int) m_cachedLines.GetCount())
|
if (pos < (int) m_cachedLines.GetCount())
|
||||||
{
|
{
|
||||||
wxRichTextLine* line = m_cachedLines.Item(pos)->GetData();
|
wxASSERT(m_cachedLinesVect.size() == m_cachedLines.GetCount());
|
||||||
|
wxRichTextLine* line = m_cachedLinesVect[pos];
|
||||||
line->Init(this);
|
line->Init(this);
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
@@ -6537,6 +6539,7 @@ wxRichTextLine* wxRichTextParagraph::AllocateLine(int pos)
|
|||||||
{
|
{
|
||||||
wxRichTextLine* line = new wxRichTextLine(this);
|
wxRichTextLine* line = new wxRichTextLine(this);
|
||||||
m_cachedLines.Append(line);
|
m_cachedLines.Append(line);
|
||||||
|
m_cachedLinesVect.push_back(line);
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6555,6 +6558,7 @@ bool wxRichTextParagraph::ClearUnusedLines(int lineCount)
|
|||||||
delete line;
|
delete line;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_cachedLinesVect.resize(lineCount);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6815,21 +6819,57 @@ bool wxRichTextPlainText::Draw(wxDC& dc, wxRichTextDrawingContext& context, cons
|
|||||||
|
|
||||||
int offset = GetRange().GetStart();
|
int offset = GetRange().GetStart();
|
||||||
|
|
||||||
wxString str = m_text;
|
const bool allSelected = selectionRange.GetStart() <= range.GetStart() && selectionRange.GetEnd() >= range.GetEnd();
|
||||||
if (context.HasVirtualText(this))
|
const bool noneSelected = selectionRange.GetEnd() < range.GetStart() || selectionRange.GetStart() > range.GetEnd();
|
||||||
|
|
||||||
|
wxString stringChunk;
|
||||||
|
wxString stringWhole;
|
||||||
|
|
||||||
|
// If nothing or everything is selected, our algorithm does not need stringWhole. It
|
||||||
|
// is enough to preprocess stringChunk only.
|
||||||
|
// In case of partial selection we need to preprocess stringWhole too.
|
||||||
|
if (allSelected || noneSelected)
|
||||||
{
|
{
|
||||||
if (!context.GetVirtualText(this, str) || str.Length() != m_text.Length())
|
const wxString* pWholeString = &m_text;
|
||||||
str = m_text;
|
if (context.HasVirtualText(this))
|
||||||
|
{
|
||||||
|
if (context.GetVirtualText(this, stringWhole) && stringWhole.Length() == m_text.Length())
|
||||||
|
pWholeString = &stringWhole;
|
||||||
|
}
|
||||||
|
|
||||||
|
long len = range.GetLength();
|
||||||
|
stringChunk = pWholeString->Mid(range.GetStart() - offset, (size_t) len);
|
||||||
|
|
||||||
|
// Replace line break characters with spaces
|
||||||
|
wxString toRemove = wxRichTextLineBreakChar;
|
||||||
|
stringChunk.Replace(toRemove, wxT(" "));
|
||||||
|
if (textAttr.HasTextEffects() &&
|
||||||
|
(textAttr.GetTextEffects() & (wxTEXT_ATTR_EFFECT_CAPITALS|wxTEXT_ATTR_EFFECT_SMALL_CAPITALS)))
|
||||||
|
{
|
||||||
|
stringChunk.MakeUpper();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stringWhole = m_text;
|
||||||
|
if (context.HasVirtualText(this))
|
||||||
|
{
|
||||||
|
if (!context.GetVirtualText(this, stringWhole) || stringWhole.Length() != m_text.Length())
|
||||||
|
stringWhole = m_text;
|
||||||
|
}
|
||||||
|
|
||||||
// Replace line break characters with spaces
|
// Replace line break characters with spaces
|
||||||
wxString toRemove = wxRichTextLineBreakChar;
|
wxString toRemove = wxRichTextLineBreakChar;
|
||||||
str.Replace(toRemove, wxT(" "));
|
stringWhole.Replace(toRemove, wxT(" "));
|
||||||
if (textAttr.HasTextEffects() && (textAttr.GetTextEffects() & (wxTEXT_ATTR_EFFECT_CAPITALS|wxTEXT_ATTR_EFFECT_SMALL_CAPITALS)))
|
if (textAttr.HasTextEffects() &&
|
||||||
str.MakeUpper();
|
(textAttr.GetTextEffects() & (wxTEXT_ATTR_EFFECT_CAPITALS|wxTEXT_ATTR_EFFECT_SMALL_CAPITALS)))
|
||||||
|
{
|
||||||
|
stringWhole.MakeUpper();
|
||||||
|
}
|
||||||
|
|
||||||
long len = range.GetLength();
|
long len = range.GetLength();
|
||||||
wxString stringChunk = str.Mid(range.GetStart() - offset, (size_t) len);
|
stringChunk = stringWhole.Mid(range.GetStart() - offset, (size_t) len);
|
||||||
|
}
|
||||||
|
|
||||||
// Test for the optimized situations where all is selected, or none
|
// Test for the optimized situations where all is selected, or none
|
||||||
// is selected.
|
// is selected.
|
||||||
@@ -6899,12 +6939,12 @@ bool wxRichTextPlainText::Draw(wxDC& dc, wxRichTextDrawingContext& context, cons
|
|||||||
// TODO: new selection code
|
// TODO: new selection code
|
||||||
|
|
||||||
// (a) All selected.
|
// (a) All selected.
|
||||||
if (selectionRange.GetStart() <= range.GetStart() && selectionRange.GetEnd() >= range.GetEnd())
|
if (allSelected)
|
||||||
{
|
{
|
||||||
DrawTabbedString(dc, textAttr, rect, stringChunk, x, y, true);
|
DrawTabbedString(dc, textAttr, rect, stringChunk, x, y, true);
|
||||||
}
|
}
|
||||||
// (b) None selected.
|
// (b) None selected.
|
||||||
else if (selectionRange.GetEnd() < range.GetStart() || selectionRange.GetStart() > range.GetEnd())
|
else if (noneSelected)
|
||||||
{
|
{
|
||||||
// Draw all unselected
|
// Draw all unselected
|
||||||
DrawTabbedString(dc, textAttr, rect, stringChunk, x, y, false);
|
DrawTabbedString(dc, textAttr, rect, stringChunk, x, y, false);
|
||||||
@@ -6914,6 +6954,8 @@ bool wxRichTextPlainText::Draw(wxDC& dc, wxRichTextDrawingContext& context, cons
|
|||||||
// (c) Part selected, part not
|
// (c) Part selected, part not
|
||||||
// Let's draw unselected chunk, selected chunk, then unselected chunk.
|
// Let's draw unselected chunk, selected chunk, then unselected chunk.
|
||||||
|
|
||||||
|
const wxString& str = stringWhole;
|
||||||
|
|
||||||
dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
|
dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
|
||||||
|
|
||||||
// 1. Initial unselected chunk, if any, up until start of selection.
|
// 1. Initial unselected chunk, if any, up until start of selection.
|
||||||
@@ -7215,23 +7257,32 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz
|
|||||||
|
|
||||||
bool haveDescent = false;
|
bool haveDescent = false;
|
||||||
int startPos = range.GetStart() - GetRange().GetStart();
|
int startPos = range.GetStart() - GetRange().GetStart();
|
||||||
long len = range.GetLength();
|
|
||||||
|
|
||||||
wxString str(m_text);
|
wxString stringChunk;
|
||||||
if (context.HasVirtualText(this))
|
|
||||||
{
|
{
|
||||||
if (!context.GetVirtualText(this, str) || str.Length() != m_text.Length())
|
// We don't need stringWhole. Only prepare stringChunk.
|
||||||
str = m_text;
|
wxString stringWhole;
|
||||||
|
const wxString* pWholeString = &m_text;
|
||||||
|
if (context.HasVirtualText(this))
|
||||||
|
{
|
||||||
|
if (context.GetVirtualText(this, stringWhole) && stringWhole.Length() == m_text.Length())
|
||||||
|
pWholeString = &stringWhole;
|
||||||
|
}
|
||||||
|
|
||||||
|
long len = range.GetLength();
|
||||||
|
stringChunk = pWholeString->Mid(startPos, (size_t) len);
|
||||||
|
|
||||||
|
// Replace line break characters with spaces
|
||||||
|
wxString toRemove = wxRichTextLineBreakChar;
|
||||||
|
stringChunk.Replace(toRemove, wxT(" "));
|
||||||
|
if (textAttr.HasTextEffects() &&
|
||||||
|
(textAttr.GetTextEffects() & (wxTEXT_ATTR_EFFECT_CAPITALS|wxTEXT_ATTR_EFFECT_SMALL_CAPITALS)))
|
||||||
|
{
|
||||||
|
stringChunk.MakeUpper();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString toReplace = wxRichTextLineBreakChar;
|
|
||||||
str.Replace(toReplace, wxT(" "));
|
|
||||||
|
|
||||||
wxString stringChunk = str.Mid(startPos, (size_t) len);
|
|
||||||
|
|
||||||
if (textAttr.HasTextEffects() && (textAttr.GetTextEffects() & (wxTEXT_ATTR_EFFECT_CAPITALS|wxTEXT_ATTR_EFFECT_SMALL_CAPITALS)))
|
|
||||||
stringChunk.MakeUpper();
|
|
||||||
|
|
||||||
wxCoord w, h;
|
wxCoord w, h;
|
||||||
int width = 0;
|
int width = 0;
|
||||||
if (stringChunk.Find(wxT('\t')) != wxNOT_FOUND)
|
if (stringChunk.Find(wxT('\t')) != wxNOT_FOUND)
|
||||||
|
Reference in New Issue
Block a user