Further wxRichTextCtrl performance improvements
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@53382 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -1698,7 +1698,7 @@ public:
|
|||||||
|
|
||||||
/// Update the control appearance
|
/// Update the control appearance
|
||||||
void UpdateAppearance(long caretPosition, bool sendUpdateEvent = false,
|
void UpdateAppearance(long caretPosition, bool sendUpdateEvent = false,
|
||||||
wxArrayInt* optimizationLineCharPositions = NULL, wxArrayInt* optimizationLineYPositions = NULL);
|
wxArrayInt* optimizationLineCharPositions = NULL, wxArrayInt* optimizationLineYPositions = NULL, bool isDoCmd = true);
|
||||||
|
|
||||||
/// Replace the buffer paragraphs with the given fragment.
|
/// Replace the buffer paragraphs with the given fragment.
|
||||||
void ApplyParagraphs(const wxRichTextParagraphLayoutBox& fragment);
|
void ApplyParagraphs(const wxRichTextParagraphLayoutBox& fragment);
|
||||||
@@ -1707,6 +1707,9 @@ public:
|
|||||||
wxRichTextParagraphLayoutBox& GetNewParagraphs() { return m_newParagraphs; }
|
wxRichTextParagraphLayoutBox& GetNewParagraphs() { return m_newParagraphs; }
|
||||||
wxRichTextParagraphLayoutBox& GetOldParagraphs() { return m_oldParagraphs; }
|
wxRichTextParagraphLayoutBox& GetOldParagraphs() { return m_oldParagraphs; }
|
||||||
|
|
||||||
|
/// Calculate arrays for refresh optimization
|
||||||
|
void CalculateRefreshOptimizations(wxArrayInt& optimizationLineCharPositions, wxArrayInt& optimizationLineYPositions);
|
||||||
|
|
||||||
/// Set/get the position used for e.g. insertion
|
/// Set/get the position used for e.g. insertion
|
||||||
void SetPosition(long pos) { m_position = pos; }
|
void SetPosition(long pos) { m_position = pos; }
|
||||||
long GetPosition() const { return m_position; }
|
long GetPosition() const { return m_position; }
|
||||||
|
@@ -683,6 +683,9 @@ public:
|
|||||||
/// Scroll into view. This takes a _caret_ position.
|
/// Scroll into view. This takes a _caret_ position.
|
||||||
virtual bool ScrollIntoView(long position, int keyCode);
|
virtual bool ScrollIntoView(long position, int keyCode);
|
||||||
|
|
||||||
|
/// Refresh the area affected by a selection change
|
||||||
|
bool RefreshForSelectionChange(const wxRichTextRange& oldSelection, const wxRichTextRange& newSelection);
|
||||||
|
|
||||||
/// The caret position is the character position just before the caret.
|
/// The caret position is the character position just before the caret.
|
||||||
/// A value of -1 means the caret is at the start of the buffer.
|
/// A value of -1 means the caret is at the start of the buffer.
|
||||||
void SetCaretPosition(long position, bool showAtLineStart = false) ;
|
void SetCaretPosition(long position, bool showAtLineStart = false) ;
|
||||||
|
@@ -589,7 +589,7 @@ bool wxRichTextParagraphLayoutBox::Draw(wxDC& dc, const wxRichTextRange& range,
|
|||||||
// Skip
|
// Skip
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
child->Draw(dc, range, selectionRange, childRect, descent, style);
|
child->Draw(dc, range, selectionRange, rect, descent, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
node = node->GetNext();
|
node = node->GetNext();
|
||||||
@@ -856,9 +856,12 @@ wxRichTextLine* wxRichTextParagraphLayoutBox::GetLineAtPosition(long pos, bool c
|
|||||||
// First find the first paragraph whose starting position is within the range.
|
// First find the first paragraph whose starting position is within the range.
|
||||||
wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
|
wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
|
||||||
while (node)
|
while (node)
|
||||||
|
{
|
||||||
|
wxRichTextObject* obj = (wxRichTextObject*) node->GetData();
|
||||||
|
if (obj->GetRange().Contains(pos))
|
||||||
{
|
{
|
||||||
// child is a paragraph
|
// child is a paragraph
|
||||||
wxRichTextParagraph* child = wxDynamicCast(node->GetData(), wxRichTextParagraph);
|
wxRichTextParagraph* child = wxDynamicCast(obj, wxRichTextParagraph);
|
||||||
wxASSERT (child != NULL);
|
wxASSERT (child != NULL);
|
||||||
|
|
||||||
wxRichTextLineList::compatibility_iterator node2 = child->GetLines().GetFirst();
|
wxRichTextLineList::compatibility_iterator node2 = child->GetLines().GetFirst();
|
||||||
@@ -877,6 +880,7 @@ wxRichTextLine* wxRichTextParagraphLayoutBox::GetLineAtPosition(long pos, bool c
|
|||||||
|
|
||||||
node2 = node2->GetNext();
|
node2 = node2->GetNext();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
node = node->GetNext();
|
node = node->GetNext();
|
||||||
}
|
}
|
||||||
@@ -3105,7 +3109,7 @@ wxRichTextParagraph::~wxRichTextParagraph()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw the item
|
/// Draw the item
|
||||||
bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& WXUNUSED(rect), int WXUNUSED(descent), int style)
|
bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int WXUNUSED(descent), int style)
|
||||||
{
|
{
|
||||||
wxTextAttr attr = GetCombinedAttributes();
|
wxTextAttr attr = GetCombinedAttributes();
|
||||||
|
|
||||||
@@ -3184,12 +3188,15 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& range, const wxR
|
|||||||
wxRichTextLine* line = node->GetData();
|
wxRichTextLine* line = node->GetData();
|
||||||
wxRichTextRange lineRange = line->GetAbsoluteRange();
|
wxRichTextRange lineRange = line->GetAbsoluteRange();
|
||||||
|
|
||||||
int maxDescent = line->GetDescent();
|
|
||||||
|
|
||||||
// Lines are specified relative to the paragraph
|
// Lines are specified relative to the paragraph
|
||||||
|
|
||||||
wxPoint linePosition = line->GetPosition() + GetPosition();
|
wxPoint linePosition = line->GetPosition() + GetPosition();
|
||||||
|
|
||||||
|
// Don't draw if off the screen
|
||||||
|
if (((style & wxRICHTEXT_DRAW_IGNORE_CACHE) != 0) || ((linePosition.y + line->GetSize().y) >= rect.y && linePosition.y <= rect.y + rect.height))
|
||||||
|
{
|
||||||
wxPoint objectPosition = linePosition;
|
wxPoint objectPosition = linePosition;
|
||||||
|
int maxDescent = line->GetDescent();
|
||||||
|
|
||||||
// Loop through objects until we get to the one within range
|
// Loop through objects until we get to the one within range
|
||||||
wxRichTextObjectList::compatibility_iterator node2 = m_children.GetFirst();
|
wxRichTextObjectList::compatibility_iterator node2 = m_children.GetFirst();
|
||||||
@@ -3231,6 +3238,7 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& range, const wxR
|
|||||||
|
|
||||||
node2 = node2->GetNext();
|
node2 = node2->GetNext();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
node = node->GetNext();
|
node = node->GetNext();
|
||||||
}
|
}
|
||||||
@@ -5548,8 +5556,6 @@ bool wxRichTextBuffer::BeginStyle(const wxTextAttr& style)
|
|||||||
|
|
||||||
SetDefaultStyle(newStyle);
|
SetDefaultStyle(newStyle);
|
||||||
|
|
||||||
// wxLogDebug("Default style size = %d", GetDefaultStyle().GetFont().GetPointSize());
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6518,18 +6524,10 @@ wxRichTextAction::~wxRichTextAction()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxRichTextAction::Do()
|
void wxRichTextAction::CalculateRefreshOptimizations(wxArrayInt& optimizationLineCharPositions, wxArrayInt& optimizationLineYPositions)
|
||||||
{
|
{
|
||||||
m_buffer->Modify(true);
|
|
||||||
|
|
||||||
switch (m_cmdId)
|
|
||||||
{
|
|
||||||
case wxRICHTEXT_INSERT:
|
|
||||||
{
|
|
||||||
// Store a list of line start character and y positions so we can figure out which area
|
// Store a list of line start character and y positions so we can figure out which area
|
||||||
// we need to refresh
|
// we need to refresh
|
||||||
wxArrayInt optimizationLineCharPositions;
|
|
||||||
wxArrayInt optimizationLineYPositions;
|
|
||||||
|
|
||||||
#if wxRICHTEXT_USE_OPTIMIZED_DRAWING
|
#if wxRICHTEXT_USE_OPTIMIZED_DRAWING
|
||||||
// NOTE: we're assuming that the buffer is laid out correctly at this point.
|
// NOTE: we're assuming that the buffer is laid out correctly at this point.
|
||||||
@@ -6576,6 +6574,24 @@ bool wxRichTextAction::Do()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxRichTextAction::Do()
|
||||||
|
{
|
||||||
|
m_buffer->Modify(true);
|
||||||
|
|
||||||
|
switch (m_cmdId)
|
||||||
|
{
|
||||||
|
case wxRICHTEXT_INSERT:
|
||||||
|
{
|
||||||
|
// Store a list of line start character and y positions so we can figure out which area
|
||||||
|
// we need to refresh
|
||||||
|
wxArrayInt optimizationLineCharPositions;
|
||||||
|
wxArrayInt optimizationLineYPositions;
|
||||||
|
|
||||||
|
#if wxRICHTEXT_USE_OPTIMIZED_DRAWING
|
||||||
|
CalculateRefreshOptimizations(optimizationLineCharPositions, optimizationLineYPositions);
|
||||||
|
#endif
|
||||||
|
|
||||||
m_buffer->InsertFragment(GetRange().GetStart(), m_newParagraphs);
|
m_buffer->InsertFragment(GetRange().GetStart(), m_newParagraphs);
|
||||||
m_buffer->UpdateRanges();
|
m_buffer->UpdateRanges();
|
||||||
@@ -6599,10 +6615,7 @@ bool wxRichTextAction::Do()
|
|||||||
|
|
||||||
newCaretPosition = wxMin(newCaretPosition, (m_buffer->GetRange().GetEnd()-1));
|
newCaretPosition = wxMin(newCaretPosition, (m_buffer->GetRange().GetEnd()-1));
|
||||||
|
|
||||||
if (optimizationLineCharPositions.GetCount() > 0)
|
UpdateAppearance(newCaretPosition, true /* send update event */, & optimizationLineCharPositions, & optimizationLineYPositions, true /* do */);
|
||||||
UpdateAppearance(newCaretPosition, true /* send update event */, & optimizationLineCharPositions, & optimizationLineYPositions);
|
|
||||||
else
|
|
||||||
UpdateAppearance(newCaretPosition, true /* send update event */);
|
|
||||||
|
|
||||||
wxRichTextEvent cmdEvent(
|
wxRichTextEvent cmdEvent(
|
||||||
wxEVT_COMMAND_RICHTEXT_CONTENT_INSERTED,
|
wxEVT_COMMAND_RICHTEXT_CONTENT_INSERTED,
|
||||||
@@ -6617,6 +6630,13 @@ bool wxRichTextAction::Do()
|
|||||||
}
|
}
|
||||||
case wxRICHTEXT_DELETE:
|
case wxRICHTEXT_DELETE:
|
||||||
{
|
{
|
||||||
|
wxArrayInt optimizationLineCharPositions;
|
||||||
|
wxArrayInt optimizationLineYPositions;
|
||||||
|
|
||||||
|
#if wxRICHTEXT_USE_OPTIMIZED_DRAWING
|
||||||
|
CalculateRefreshOptimizations(optimizationLineCharPositions, optimizationLineYPositions);
|
||||||
|
#endif
|
||||||
|
|
||||||
m_buffer->DeleteRange(GetRange());
|
m_buffer->DeleteRange(GetRange());
|
||||||
m_buffer->UpdateRanges();
|
m_buffer->UpdateRanges();
|
||||||
m_buffer->Invalidate(wxRichTextRange(GetRange().GetStart(), GetRange().GetStart()));
|
m_buffer->Invalidate(wxRichTextRange(GetRange().GetStart(), GetRange().GetStart()));
|
||||||
@@ -6625,7 +6645,7 @@ bool wxRichTextAction::Do()
|
|||||||
if (caretPos >= m_buffer->GetRange().GetEnd())
|
if (caretPos >= m_buffer->GetRange().GetEnd())
|
||||||
caretPos --;
|
caretPos --;
|
||||||
|
|
||||||
UpdateAppearance(caretPos, true /* send update event */);
|
UpdateAppearance(caretPos, true /* send update event */, & optimizationLineCharPositions, & optimizationLineYPositions, true /* do */);
|
||||||
|
|
||||||
wxRichTextEvent cmdEvent(
|
wxRichTextEvent cmdEvent(
|
||||||
wxEVT_COMMAND_RICHTEXT_CONTENT_DELETED,
|
wxEVT_COMMAND_RICHTEXT_CONTENT_DELETED,
|
||||||
@@ -6671,13 +6691,20 @@ bool wxRichTextAction::Undo()
|
|||||||
{
|
{
|
||||||
case wxRICHTEXT_INSERT:
|
case wxRICHTEXT_INSERT:
|
||||||
{
|
{
|
||||||
|
wxArrayInt optimizationLineCharPositions;
|
||||||
|
wxArrayInt optimizationLineYPositions;
|
||||||
|
|
||||||
|
#if wxRICHTEXT_USE_OPTIMIZED_DRAWING
|
||||||
|
CalculateRefreshOptimizations(optimizationLineCharPositions, optimizationLineYPositions);
|
||||||
|
#endif
|
||||||
|
|
||||||
m_buffer->DeleteRange(GetRange());
|
m_buffer->DeleteRange(GetRange());
|
||||||
m_buffer->UpdateRanges();
|
m_buffer->UpdateRanges();
|
||||||
m_buffer->Invalidate(wxRichTextRange(GetRange().GetStart(), GetRange().GetStart()));
|
m_buffer->Invalidate(wxRichTextRange(GetRange().GetStart(), GetRange().GetStart()));
|
||||||
|
|
||||||
long newCaretPosition = GetPosition() - 1;
|
long newCaretPosition = GetPosition() - 1;
|
||||||
|
|
||||||
UpdateAppearance(newCaretPosition, true /* send update event */);
|
UpdateAppearance(newCaretPosition, true, /* send update event */ & optimizationLineCharPositions, & optimizationLineYPositions, false /* undo */);
|
||||||
|
|
||||||
wxRichTextEvent cmdEvent(
|
wxRichTextEvent cmdEvent(
|
||||||
wxEVT_COMMAND_RICHTEXT_CONTENT_DELETED,
|
wxEVT_COMMAND_RICHTEXT_CONTENT_DELETED,
|
||||||
@@ -6692,11 +6719,18 @@ bool wxRichTextAction::Undo()
|
|||||||
}
|
}
|
||||||
case wxRICHTEXT_DELETE:
|
case wxRICHTEXT_DELETE:
|
||||||
{
|
{
|
||||||
|
wxArrayInt optimizationLineCharPositions;
|
||||||
|
wxArrayInt optimizationLineYPositions;
|
||||||
|
|
||||||
|
#if wxRICHTEXT_USE_OPTIMIZED_DRAWING
|
||||||
|
CalculateRefreshOptimizations(optimizationLineCharPositions, optimizationLineYPositions);
|
||||||
|
#endif
|
||||||
|
|
||||||
m_buffer->InsertFragment(GetRange().GetStart(), m_oldParagraphs);
|
m_buffer->InsertFragment(GetRange().GetStart(), m_oldParagraphs);
|
||||||
m_buffer->UpdateRanges();
|
m_buffer->UpdateRanges();
|
||||||
m_buffer->Invalidate(GetRange());
|
m_buffer->Invalidate(GetRange());
|
||||||
|
|
||||||
UpdateAppearance(GetPosition(), true /* send update event */);
|
UpdateAppearance(GetPosition(), true, /* send update event */ & optimizationLineCharPositions, & optimizationLineYPositions, false /* undo */);
|
||||||
|
|
||||||
wxRichTextEvent cmdEvent(
|
wxRichTextEvent cmdEvent(
|
||||||
wxEVT_COMMAND_RICHTEXT_CONTENT_INSERTED,
|
wxEVT_COMMAND_RICHTEXT_CONTENT_INSERTED,
|
||||||
@@ -6735,7 +6769,7 @@ bool wxRichTextAction::Undo()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Update the control appearance
|
/// Update the control appearance
|
||||||
void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent, wxArrayInt* optimizationLineCharPositions, wxArrayInt* optimizationLineYPositions)
|
void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent, wxArrayInt* optimizationLineCharPositions, wxArrayInt* optimizationLineYPositions, bool isDoCmd)
|
||||||
{
|
{
|
||||||
if (m_ctrl)
|
if (m_ctrl)
|
||||||
{
|
{
|
||||||
@@ -6746,7 +6780,7 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent
|
|||||||
|
|
||||||
#if wxRICHTEXT_USE_OPTIMIZED_DRAWING
|
#if wxRICHTEXT_USE_OPTIMIZED_DRAWING
|
||||||
// Find refresh rectangle if we are in a position to optimise refresh
|
// Find refresh rectangle if we are in a position to optimise refresh
|
||||||
if (m_cmdId == wxRICHTEXT_INSERT && optimizationLineCharPositions && optimizationLineCharPositions->GetCount() > 0)
|
if ((m_cmdId == wxRICHTEXT_INSERT || m_cmdId == wxRICHTEXT_DELETE) && optimizationLineCharPositions)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
@@ -6757,17 +6791,57 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent
|
|||||||
int firstY = 0;
|
int firstY = 0;
|
||||||
int lastY = firstVisiblePt.y + clientSize.y;
|
int lastY = firstVisiblePt.y + clientSize.y;
|
||||||
|
|
||||||
bool foundStart = false;
|
|
||||||
bool foundEnd = false;
|
bool foundEnd = false;
|
||||||
|
|
||||||
// position offset - how many characters were inserted
|
// position offset - how many characters were inserted
|
||||||
int positionOffset = GetRange().GetLength();
|
int positionOffset = GetRange().GetLength();
|
||||||
|
|
||||||
|
// Determine whether this is Do or Undo, and adjust positionOffset accordingly
|
||||||
|
if ((m_cmdId == wxRICHTEXT_DELETE && isDoCmd) || (m_cmdId == wxRICHTEXT_INSERT && !isDoCmd))
|
||||||
|
positionOffset = - positionOffset;
|
||||||
|
|
||||||
// find the first line which is being drawn at the same position as it was
|
// find the first line which is being drawn at the same position as it was
|
||||||
// before. Since we're talking about a simple insertion, we can assume
|
// before. Since we're talking about a simple insertion, we can assume
|
||||||
// that the rest of the window does not need to be redrawn.
|
// that the rest of the window does not need to be redrawn.
|
||||||
|
|
||||||
wxRichTextParagraph* para = m_buffer->GetParagraphAtPosition(GetPosition());
|
wxRichTextParagraph* para = m_buffer->GetParagraphAtPosition(GetPosition());
|
||||||
|
if (para)
|
||||||
|
{
|
||||||
|
// Find line containing GetPosition().
|
||||||
|
wxRichTextLine* line = NULL;
|
||||||
|
wxRichTextLineList::compatibility_iterator node2 = para->GetLines().GetFirst();
|
||||||
|
while (node2)
|
||||||
|
{
|
||||||
|
wxRichTextLine* l = node2->GetData();
|
||||||
|
wxRichTextRange range = l->GetAbsoluteRange();
|
||||||
|
if (range.Contains(GetRange().GetStart()-1))
|
||||||
|
{
|
||||||
|
line = l;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
node2 = node2->GetNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line)
|
||||||
|
{
|
||||||
|
// Step back a couple of lines to where we can be sure of reformatting correctly
|
||||||
|
wxRichTextLineList::compatibility_iterator lineNode = para->GetLines().Find(line);
|
||||||
|
if (lineNode)
|
||||||
|
{
|
||||||
|
lineNode = lineNode->GetPrevious();
|
||||||
|
if (lineNode)
|
||||||
|
{
|
||||||
|
line = (wxRichTextLine*) lineNode->GetData();
|
||||||
|
lineNode = lineNode->GetPrevious();
|
||||||
|
if (lineNode)
|
||||||
|
line = (wxRichTextLine*) lineNode->GetData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
firstY = line->GetAbsolutePosition().y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wxRichTextObjectList::compatibility_iterator node = m_buffer->GetChildren().Find(para);
|
wxRichTextObjectList::compatibility_iterator node = m_buffer->GetChildren().Find(para);
|
||||||
while (node)
|
while (node)
|
||||||
{
|
{
|
||||||
@@ -6787,14 +6861,19 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent
|
|||||||
node2 = wxRichTextLineList::compatibility_iterator();
|
node2 = wxRichTextLineList::compatibility_iterator();
|
||||||
node = wxRichTextObjectList::compatibility_iterator();
|
node = wxRichTextObjectList::compatibility_iterator();
|
||||||
}
|
}
|
||||||
|
// Detect last line in the buffer
|
||||||
|
else if (!node2->GetNext() && para->GetRange().Contains(m_buffer->GetRange().GetEnd()))
|
||||||
|
{
|
||||||
|
foundEnd = true;
|
||||||
|
lastY = pt.y + line->GetSize().y;
|
||||||
|
|
||||||
|
node2 = wxRichTextLineList::compatibility_iterator();
|
||||||
|
node = wxRichTextObjectList::compatibility_iterator();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!foundStart)
|
|
||||||
{
|
|
||||||
firstY = pt.y - firstVisiblePt.y;
|
|
||||||
foundStart = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// search for this line being at the same position as before
|
// search for this line being at the same position as before
|
||||||
for (i = 0; i < optimizationLineCharPositions->GetCount(); i++)
|
for (i = 0; i < optimizationLineCharPositions->GetCount(); i++)
|
||||||
{
|
{
|
||||||
@@ -6803,7 +6882,8 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent
|
|||||||
{
|
{
|
||||||
// Stop, we're now the same as we were
|
// Stop, we're now the same as we were
|
||||||
foundEnd = true;
|
foundEnd = true;
|
||||||
lastY = pt.y - firstVisiblePt.y;
|
|
||||||
|
lastY = pt.y;
|
||||||
|
|
||||||
node2 = wxRichTextLineList::compatibility_iterator();
|
node2 = wxRichTextLineList::compatibility_iterator();
|
||||||
node = wxRichTextObjectList::compatibility_iterator();
|
node = wxRichTextObjectList::compatibility_iterator();
|
||||||
@@ -6821,17 +6901,13 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent
|
|||||||
node = node->GetNext();
|
node = node->GetNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!foundStart)
|
firstY = wxMax(firstVisiblePt.y, firstY);
|
||||||
firstY = firstVisiblePt.y;
|
|
||||||
if (!foundEnd)
|
if (!foundEnd)
|
||||||
lastY = firstVisiblePt.y + clientSize.y;
|
lastY = firstVisiblePt.y + clientSize.y;
|
||||||
|
|
||||||
wxRect rect(firstVisiblePt.x, firstY, firstVisiblePt.x + clientSize.x, lastY - firstY);
|
// Convert to device coordinates
|
||||||
|
wxRect rect(m_ctrl->GetPhysicalPoint(wxPoint(firstVisiblePt.x, firstY)), wxSize(clientSize.x, lastY - firstY));
|
||||||
m_ctrl->RefreshRect(rect);
|
m_ctrl->RefreshRect(rect);
|
||||||
|
|
||||||
// TODO: we need to make sure that lines are only drawn if in the update region. The rect
|
|
||||||
// passed to Draw is currently used in different ways (to pass the position the content should
|
|
||||||
// be drawn at as well as the relevant region).
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
@@ -364,14 +364,10 @@ void wxRichTextCtrl::OnLeftClick(wxMouseEvent& event)
|
|||||||
|
|
||||||
if (event.ShiftDown())
|
if (event.ShiftDown())
|
||||||
{
|
{
|
||||||
bool extendSel = false;
|
|
||||||
if (m_selectionRange.GetStart() == -2)
|
if (m_selectionRange.GetStart() == -2)
|
||||||
extendSel = ExtendSelection(oldCaretPos, m_caretPosition, wxRICHTEXT_SHIFT_DOWN);
|
ExtendSelection(oldCaretPos, m_caretPosition, wxRICHTEXT_SHIFT_DOWN);
|
||||||
else
|
else
|
||||||
extendSel = ExtendSelection(m_caretPosition, m_caretPosition, wxRICHTEXT_SHIFT_DOWN);
|
ExtendSelection(m_caretPosition, m_caretPosition, wxRICHTEXT_SHIFT_DOWN);
|
||||||
|
|
||||||
if (extendSel)
|
|
||||||
Refresh(false);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SelectNone();
|
SelectNone();
|
||||||
@@ -500,13 +496,10 @@ void wxRichTextCtrl::OnMoveMouse(wxMouseEvent& event)
|
|||||||
|
|
||||||
if (m_caretPosition != position)
|
if (m_caretPosition != position)
|
||||||
{
|
{
|
||||||
bool extendSel = ExtendSelection(m_caretPosition, position, wxRICHTEXT_SHIFT_DOWN);
|
ExtendSelection(m_caretPosition, position, wxRICHTEXT_SHIFT_DOWN);
|
||||||
|
|
||||||
MoveCaret(position, caretAtLineStart);
|
MoveCaret(position, caretAtLineStart);
|
||||||
SetDefaultStyleToCursorStyle();
|
SetDefaultStyleToCursorStyle();
|
||||||
|
|
||||||
if (extendSel)
|
|
||||||
Refresh(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1006,6 +999,8 @@ bool wxRichTextCtrl::ExtendSelection(long oldPos, long newPos, int flags)
|
|||||||
{
|
{
|
||||||
if (flags & wxRICHTEXT_SHIFT_DOWN)
|
if (flags & wxRICHTEXT_SHIFT_DOWN)
|
||||||
{
|
{
|
||||||
|
wxRichTextRange oldSelection = m_selectionRange;
|
||||||
|
|
||||||
// If not currently selecting, start selecting
|
// If not currently selecting, start selecting
|
||||||
if (m_selectionRange.GetStart() == -2)
|
if (m_selectionRange.GetStart() == -2)
|
||||||
{
|
{
|
||||||
@@ -1026,6 +1021,8 @@ bool wxRichTextCtrl::ExtendSelection(long oldPos, long newPos, int flags)
|
|||||||
m_selectionRange.SetRange(newPos+1, m_selectionAnchor);
|
m_selectionRange.SetRange(newPos+1, m_selectionAnchor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RefreshForSelectionChange(oldSelection, m_selectionRange);
|
||||||
|
|
||||||
if (m_selectionRange.GetStart() > m_selectionRange.GetEnd())
|
if (m_selectionRange.GetStart() > m_selectionRange.GetEnd())
|
||||||
{
|
{
|
||||||
wxLogDebug(wxT("Strange selection range"));
|
wxLogDebug(wxT("Strange selection range"));
|
||||||
@@ -1297,8 +1294,6 @@ bool wxRichTextCtrl::MoveRight(int noPositions, int flags)
|
|||||||
PositionCaret();
|
PositionCaret();
|
||||||
SetDefaultStyleToCursorStyle();
|
SetDefaultStyleToCursorStyle();
|
||||||
|
|
||||||
if (extendSel)
|
|
||||||
Refresh(false);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1326,8 +1321,6 @@ bool wxRichTextCtrl::MoveLeft(int noPositions, int flags)
|
|||||||
PositionCaret();
|
PositionCaret();
|
||||||
SetDefaultStyleToCursorStyle();
|
SetDefaultStyleToCursorStyle();
|
||||||
|
|
||||||
if (extendSel)
|
|
||||||
Refresh(false);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1417,8 +1410,6 @@ bool wxRichTextCtrl::MoveDown(int noLines, int flags)
|
|||||||
PositionCaret();
|
PositionCaret();
|
||||||
SetDefaultStyleToCursorStyle();
|
SetDefaultStyleToCursorStyle();
|
||||||
|
|
||||||
if (extendSel)
|
|
||||||
Refresh(false);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1440,8 +1431,6 @@ bool wxRichTextCtrl::MoveToParagraphEnd(int flags)
|
|||||||
PositionCaret();
|
PositionCaret();
|
||||||
SetDefaultStyleToCursorStyle();
|
SetDefaultStyleToCursorStyle();
|
||||||
|
|
||||||
if (extendSel)
|
|
||||||
Refresh(false);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1463,8 +1452,6 @@ bool wxRichTextCtrl::MoveToParagraphStart(int flags)
|
|||||||
PositionCaret();
|
PositionCaret();
|
||||||
SetDefaultStyleToCursorStyle();
|
SetDefaultStyleToCursorStyle();
|
||||||
|
|
||||||
if (extendSel)
|
|
||||||
Refresh(false);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1488,8 +1475,6 @@ bool wxRichTextCtrl::MoveToLineEnd(int flags)
|
|||||||
PositionCaret();
|
PositionCaret();
|
||||||
SetDefaultStyleToCursorStyle();
|
SetDefaultStyleToCursorStyle();
|
||||||
|
|
||||||
if (extendSel)
|
|
||||||
Refresh(false);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1515,8 +1500,6 @@ bool wxRichTextCtrl::MoveToLineStart(int flags)
|
|||||||
PositionCaret();
|
PositionCaret();
|
||||||
SetDefaultStyleToCursorStyle();
|
SetDefaultStyleToCursorStyle();
|
||||||
|
|
||||||
if (extendSel)
|
|
||||||
Refresh(false);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1536,8 +1519,6 @@ bool wxRichTextCtrl::MoveHome(int flags)
|
|||||||
PositionCaret();
|
PositionCaret();
|
||||||
SetDefaultStyleToCursorStyle();
|
SetDefaultStyleToCursorStyle();
|
||||||
|
|
||||||
if (extendSel)
|
|
||||||
Refresh(false);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1559,8 +1540,6 @@ bool wxRichTextCtrl::MoveEnd(int flags)
|
|||||||
PositionCaret();
|
PositionCaret();
|
||||||
SetDefaultStyleToCursorStyle();
|
SetDefaultStyleToCursorStyle();
|
||||||
|
|
||||||
if (extendSel)
|
|
||||||
Refresh(false);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1600,8 +1579,6 @@ bool wxRichTextCtrl::PageDown(int noPages, int flags)
|
|||||||
PositionCaret();
|
PositionCaret();
|
||||||
SetDefaultStyleToCursorStyle();
|
SetDefaultStyleToCursorStyle();
|
||||||
|
|
||||||
if (extendSel)
|
|
||||||
Refresh(false);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1719,8 +1696,6 @@ bool wxRichTextCtrl::WordLeft(int WXUNUSED(n), int flags)
|
|||||||
PositionCaret();
|
PositionCaret();
|
||||||
SetDefaultStyleToCursorStyle();
|
SetDefaultStyleToCursorStyle();
|
||||||
|
|
||||||
if (extendSel)
|
|
||||||
Refresh(false);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1743,8 +1718,6 @@ bool wxRichTextCtrl::WordRight(int WXUNUSED(n), int flags)
|
|||||||
PositionCaret();
|
PositionCaret();
|
||||||
SetDefaultStyleToCursorStyle();
|
SetDefaultStyleToCursorStyle();
|
||||||
|
|
||||||
if (extendSel)
|
|
||||||
Refresh(false);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1831,14 +1804,31 @@ void wxRichTextCtrl::SetupScrollbars(bool atTop)
|
|||||||
if (!atTop)
|
if (!atTop)
|
||||||
GetViewStart(& startX, & startY);
|
GetViewStart(& startX, & startY);
|
||||||
|
|
||||||
int maxPositionX = 0; // wxMax(sz.x - clientSize.x, 0);
|
int maxPositionX = 0;
|
||||||
int maxPositionY = (int) ((((float)(wxMax((unitsY*pixelsPerUnit) - clientSize.y, 0)))/((float)pixelsPerUnit)) + 0.5);
|
int maxPositionY = (int) ((((float)(wxMax((unitsY*pixelsPerUnit) - clientSize.y, 0)))/((float)pixelsPerUnit)) + 0.5);
|
||||||
|
|
||||||
|
int newStartX = wxMin(maxPositionX, startX);
|
||||||
|
int newStartY = wxMin(maxPositionY, startY);
|
||||||
|
|
||||||
|
int oldPPUX, oldPPUY;
|
||||||
|
int oldStartX, oldStartY;
|
||||||
|
int oldVirtualSizeX = 0, oldVirtualSizeY = 0;
|
||||||
|
GetScrollPixelsPerUnit(& oldPPUX, & oldPPUY);
|
||||||
|
GetViewStart(& oldStartX, & oldStartY);
|
||||||
|
GetVirtualSize(& oldVirtualSizeX, & oldVirtualSizeY);
|
||||||
|
if (oldPPUY > 0)
|
||||||
|
oldVirtualSizeY /= oldPPUY;
|
||||||
|
|
||||||
|
if (oldPPUX == 0 && oldPPUY == pixelsPerUnit && oldVirtualSizeY == unitsY && oldStartX == newStartX && oldStartY == newStartY)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Don't set scrollbars if there were none before, and there will be none now.
|
||||||
|
if (oldPPUY != 0 && (oldVirtualSizeY < clientSize.y) && (unitsY*pixelsPerUnit < clientSize.y))
|
||||||
|
return;
|
||||||
|
|
||||||
// Move to previous scroll position if
|
// Move to previous scroll position if
|
||||||
// possible
|
// possible
|
||||||
SetScrollbars(0, pixelsPerUnit,
|
SetScrollbars(0, pixelsPerUnit, 0, unitsY, newStartX, newStartY);
|
||||||
0, unitsY,
|
|
||||||
wxMin(maxPositionX, startX), wxMin(maxPositionY, startY));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Paint the background
|
/// Paint the background
|
||||||
@@ -1957,8 +1947,11 @@ void wxRichTextCtrl::SelectNone()
|
|||||||
{
|
{
|
||||||
if (!(GetSelectionRange() == wxRichTextRange(-2, -2)))
|
if (!(GetSelectionRange() == wxRichTextRange(-2, -2)))
|
||||||
{
|
{
|
||||||
Refresh(false);
|
wxRichTextRange oldSelection = m_selectionRange;
|
||||||
|
|
||||||
m_selectionRange = wxRichTextRange(-2, -2);
|
m_selectionRange = wxRichTextRange(-2, -2);
|
||||||
|
|
||||||
|
RefreshForSelectionChange(oldSelection, m_selectionRange);
|
||||||
}
|
}
|
||||||
m_selectionAnchor = -2;
|
m_selectionAnchor = -2;
|
||||||
}
|
}
|
||||||
@@ -2357,12 +2350,13 @@ void wxRichTextCtrl::DoSetSelection(long from, long to, bool WXUNUSED(scrollCare
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
wxRichTextRange oldSelection = m_selectionRange;
|
||||||
m_selectionAnchor = from;
|
m_selectionAnchor = from;
|
||||||
m_selectionRange.SetRange(from, to-1);
|
m_selectionRange.SetRange(from, to-1);
|
||||||
if (from > -2)
|
if (from > -2)
|
||||||
m_caretPosition = from-1;
|
m_caretPosition = from-1;
|
||||||
|
|
||||||
Refresh(false);
|
RefreshForSelectionChange(oldSelection, m_selectionRange);
|
||||||
PositionCaret();
|
PositionCaret();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3195,5 +3189,53 @@ void wxRichTextCtrl::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event)
|
|||||||
Refresh();
|
Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Refresh the area affected by a selection change
|
||||||
|
bool wxRichTextCtrl::RefreshForSelectionChange(const wxRichTextRange& oldSelection, const wxRichTextRange& newSelection)
|
||||||
|
{
|
||||||
|
// Calculate the refresh rectangle - just the affected lines
|
||||||
|
long firstPos, lastPos;
|
||||||
|
if (oldSelection.GetStart() == -2 && newSelection.GetStart() != -2)
|
||||||
|
{
|
||||||
|
firstPos = newSelection.GetStart();
|
||||||
|
lastPos = newSelection.GetEnd();
|
||||||
|
}
|
||||||
|
else if (oldSelection.GetStart() != -2 && newSelection.GetStart() == -2)
|
||||||
|
{
|
||||||
|
firstPos = oldSelection.GetStart();
|
||||||
|
lastPos = oldSelection.GetEnd();
|
||||||
|
}
|
||||||
|
else if (oldSelection.GetStart() == -2 && newSelection.GetStart() == -2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
firstPos = wxMin(oldSelection.GetStart(), newSelection.GetStart());
|
||||||
|
lastPos = wxMax(oldSelection.GetEnd(), newSelection.GetEnd());
|
||||||
|
}
|
||||||
|
|
||||||
|
wxRichTextLine* firstLine = GetBuffer().GetLineAtPosition(firstPos);
|
||||||
|
wxRichTextLine* lastLine = GetBuffer().GetLineAtPosition(lastPos);
|
||||||
|
|
||||||
|
if (firstLine && lastLine)
|
||||||
|
{
|
||||||
|
wxSize clientSize = GetClientSize();
|
||||||
|
wxPoint pt1 = GetPhysicalPoint(firstLine->GetAbsolutePosition());
|
||||||
|
wxPoint pt2 = GetPhysicalPoint(lastLine->GetAbsolutePosition()) + wxPoint(0, lastLine->GetSize().y);
|
||||||
|
|
||||||
|
pt1.x = 0;
|
||||||
|
pt1.y = wxMax(0, pt1.y);
|
||||||
|
pt2.x = 0;
|
||||||
|
pt2.y = wxMin(clientSize.y, pt2.y);
|
||||||
|
|
||||||
|
wxRect rect(pt1, wxSize(clientSize.x, pt2.y - pt1.y));
|
||||||
|
RefreshRect(rect, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Refresh(false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
// wxUSE_RICHTEXT
|
// wxUSE_RICHTEXT
|
||||||
|
Reference in New Issue
Block a user