Optimized wxRTC insertion and deletion when floating objects are present.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@75884 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -31,6 +31,7 @@ All (GUI):
|
|||||||
- Add default ctor and Create() to wxContextHelpButton (Hanmac).
|
- Add default ctor and Create() to wxContextHelpButton (Hanmac).
|
||||||
- Send events when toggling wxPropertyGrid nodes from keyboard (Armel Asselin).
|
- Send events when toggling wxPropertyGrid nodes from keyboard (Armel Asselin).
|
||||||
- Fix wxRearrangeList::Check() which asserted and misbehaved before.
|
- Fix wxRearrangeList::Check() which asserted and misbehaved before.
|
||||||
|
- Optimized wxRTC insertion and deletion when floating objects are present.
|
||||||
|
|
||||||
wxGTK:
|
wxGTK:
|
||||||
|
|
||||||
|
@@ -4283,6 +4283,8 @@ public:
|
|||||||
virtual ~wxRichTextParagraph();
|
virtual ~wxRichTextParagraph();
|
||||||
wxRichTextParagraph(const wxRichTextParagraph& obj): wxRichTextCompositeObject() { Copy(obj); }
|
wxRichTextParagraph(const wxRichTextParagraph& obj): wxRichTextCompositeObject() { Copy(obj); }
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
|
||||||
// Overridables
|
// Overridables
|
||||||
|
|
||||||
virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style);
|
virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style);
|
||||||
@@ -4416,11 +4418,24 @@ public:
|
|||||||
*/
|
*/
|
||||||
void LayoutFloat(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style, wxRichTextFloatCollector* floatCollector);
|
void LayoutFloat(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style, wxRichTextFloatCollector* floatCollector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Whether the paragraph is impacted by floating objects from above.
|
||||||
|
*/
|
||||||
|
int GetImpactedByFloatingObjects() const { return m_impactedByFloatingObjects; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets whether the paragraph is impacted by floating objects from above.
|
||||||
|
*/
|
||||||
|
void SetImpactedByFloatingObjects(int i) { m_impactedByFloatingObjects = i; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// The lines that make up the wrapped paragraph
|
// The lines that make up the wrapped paragraph
|
||||||
wxRichTextLineList m_cachedLines;
|
wxRichTextLineList m_cachedLines;
|
||||||
|
|
||||||
|
// Whether the paragraph is impacted by floating objects from above
|
||||||
|
int m_impactedByFloatingObjects;
|
||||||
|
|
||||||
// Default tabstops
|
// Default tabstops
|
||||||
static wxArrayInt sm_defaultTabs;
|
static wxArrayInt sm_defaultTabs;
|
||||||
|
|
||||||
@@ -6163,7 +6178,9 @@ public:
|
|||||||
Updates the control appearance, optimizing if possible given information from the call to Layout.
|
Updates the control appearance, optimizing if possible given information from the call to Layout.
|
||||||
*/
|
*/
|
||||||
void UpdateAppearance(long caretPosition, bool sendUpdateEvent = false,
|
void UpdateAppearance(long caretPosition, bool sendUpdateEvent = false,
|
||||||
wxArrayInt* optimizationLineCharPositions = NULL, wxArrayInt* optimizationLineYPositions = NULL, bool isDoCmd = true);
|
const wxRect& oldFloatRect = wxRect(),
|
||||||
|
wxArrayInt* optimizationLineCharPositions = NULL, wxArrayInt* optimizationLineYPositions = NULL,
|
||||||
|
bool isDoCmd = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Replaces the buffer paragraphs with the given fragment.
|
Replaces the buffer paragraphs with the given fragment.
|
||||||
@@ -6216,7 +6233,8 @@ public:
|
|||||||
/**
|
/**
|
||||||
Calculate arrays for refresh optimization.
|
Calculate arrays for refresh optimization.
|
||||||
*/
|
*/
|
||||||
void CalculateRefreshOptimizations(wxArrayInt& optimizationLineCharPositions, wxArrayInt& optimizationLineYPositions);
|
void CalculateRefreshOptimizations(wxArrayInt& optimizationLineCharPositions, wxArrayInt& optimizationLineYPositions,
|
||||||
|
wxRect& oldFloatRect);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Sets the position used for e.g. insertion.
|
Sets the position used for e.g. insertion.
|
||||||
|
@@ -4124,6 +4124,8 @@ public:
|
|||||||
virtual ~wxRichTextParagraph();
|
virtual ~wxRichTextParagraph();
|
||||||
wxRichTextParagraph(const wxRichTextParagraph& obj): wxRichTextCompositeObject() { Copy(obj); }
|
wxRichTextParagraph(const wxRichTextParagraph& obj): wxRichTextCompositeObject() { Copy(obj); }
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
|
||||||
// Overridables
|
// Overridables
|
||||||
|
|
||||||
virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style);
|
virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style);
|
||||||
@@ -4257,11 +4259,24 @@ public:
|
|||||||
*/
|
*/
|
||||||
void LayoutFloat(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style, wxRichTextFloatCollector* floatCollector);
|
void LayoutFloat(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style, wxRichTextFloatCollector* floatCollector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Whether the paragraph is impacted by floating objects from above.
|
||||||
|
*/
|
||||||
|
int GetImpactedByFloatingObjects() const { return m_impactedByFloatingObjects; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets whether the paragraph is impacted by floating objects from above.
|
||||||
|
*/
|
||||||
|
void SetImpactedByFloatingObjects(int i) { m_impactedByFloatingObjects = i; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// The lines that make up the wrapped paragraph
|
// The lines that make up the wrapped paragraph
|
||||||
wxRichTextLineList m_cachedLines;
|
wxRichTextLineList m_cachedLines;
|
||||||
|
|
||||||
|
// Whether the paragraph is impacted by floating objects from above
|
||||||
|
int m_impactedByFloatingObjects;
|
||||||
|
|
||||||
// Default tabstops
|
// Default tabstops
|
||||||
static wxArrayInt sm_defaultTabs;
|
static wxArrayInt sm_defaultTabs;
|
||||||
|
|
||||||
@@ -5971,7 +5986,9 @@ public:
|
|||||||
Updates the control appearance, optimizing if possible given information from the call to Layout.
|
Updates the control appearance, optimizing if possible given information from the call to Layout.
|
||||||
*/
|
*/
|
||||||
void UpdateAppearance(long caretPosition, bool sendUpdateEvent = false,
|
void UpdateAppearance(long caretPosition, bool sendUpdateEvent = false,
|
||||||
wxArrayInt* optimizationLineCharPositions = NULL, wxArrayInt* optimizationLineYPositions = NULL, bool isDoCmd = true);
|
const wxRect& oldFloatRect = wxRect(),
|
||||||
|
wxArrayInt* optimizationLineCharPositions = NULL, wxArrayInt* optimizationLineYPositions = NULL,
|
||||||
|
bool isDoCmd = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Replaces the buffer paragraphs with the given fragment.
|
Replaces the buffer paragraphs with the given fragment.
|
||||||
@@ -6026,7 +6043,8 @@ public:
|
|||||||
/**
|
/**
|
||||||
Calculate arrays for refresh optimization.
|
Calculate arrays for refresh optimization.
|
||||||
*/
|
*/
|
||||||
void CalculateRefreshOptimizations(wxArrayInt& optimizationLineCharPositions, wxArrayInt& optimizationLineYPositions);
|
void CalculateRefreshOptimizations(wxArrayInt& optimizationLineCharPositions, wxArrayInt& optimizationLineYPositions,
|
||||||
|
wxRect& oldFloatRect);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Sets the position used for e.g. insertion.
|
Sets the position used for e.g. insertion.
|
||||||
|
@@ -2207,10 +2207,8 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, wxRichTextDrawingContext& co
|
|||||||
maxMaxWidth = wxMax(maxMaxWidth, child->GetMaxSize().x);
|
maxMaxWidth = wxMax(maxMaxWidth, child->GetMaxSize().x);
|
||||||
|
|
||||||
// If we're just formatting the visible part of the buffer,
|
// If we're just formatting the visible part of the buffer,
|
||||||
// and we're now past the bottom of the window, and we don't have any
|
// and we're now past the bottom of the window, start quick layout.
|
||||||
// floating objects (since they may cause wrapping to change for the rest of the
|
if (!hasVerticalAlignment && formatRect && child->GetPosition().y > rect.GetBottom())
|
||||||
// the buffer), start quick layout.
|
|
||||||
if (!hasVerticalAlignment && formatRect && child->GetPosition().y > rect.GetBottom() && GetFloatingObjectCount() == 0)
|
|
||||||
forceQuickLayout = true;
|
forceQuickLayout = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2220,7 +2218,47 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, wxRichTextDrawingContext& co
|
|||||||
// been laid out and have wrapped line lists associated with them.
|
// been laid out and have wrapped line lists associated with them.
|
||||||
// TODO: check all paragraphs before the affected range.
|
// TODO: check all paragraphs before the affected range.
|
||||||
|
|
||||||
int inc = availableSpace.y - child->GetPosition().y;
|
// Lay out paragraphs until they are (and were) not affected
|
||||||
|
// by floating objects from above the paragraphs.
|
||||||
|
if (wxRichTextBuffer::GetFloatingLayoutMode())
|
||||||
|
{
|
||||||
|
while (node)
|
||||||
|
{
|
||||||
|
child = wxDynamicCast(node->GetData(), wxRichTextParagraph);
|
||||||
|
if (child)
|
||||||
|
{
|
||||||
|
int oldImpactedByFloats = child->GetImpactedByFloatingObjects();
|
||||||
|
|
||||||
|
child->SetImpactedByFloatingObjects(-1);
|
||||||
|
|
||||||
|
child->LayoutToBestSize(dc, context, GetBuffer(),
|
||||||
|
attr, child->GetAttributes(), availableSpace, rect, style&~wxRICHTEXT_LAYOUT_SPECIFIED_RECT);
|
||||||
|
|
||||||
|
availableSpace.y += child->GetCachedSize().y;
|
||||||
|
maxWidth = wxMax(maxWidth, child->GetCachedSize().x);
|
||||||
|
maxMinWidth = wxMax(maxMinWidth, child->GetMinSize().x);
|
||||||
|
maxMaxWidth = wxMax(maxMaxWidth, child->GetMaxSize().x);
|
||||||
|
|
||||||
|
int newImpactedByFloats = child->GetImpactedByFloatingObjects();
|
||||||
|
|
||||||
|
// We can stop laying out if this paragraph is unaffected by floating
|
||||||
|
// objects, and was previously too.
|
||||||
|
if (oldImpactedByFloats == 0 && newImpactedByFloats == 0)
|
||||||
|
{
|
||||||
|
node = node->GetNext();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node = node->GetNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int inc = 0;
|
||||||
|
if (node)
|
||||||
|
{
|
||||||
|
child = wxDynamicCast(node->GetData(), wxRichTextParagraph);
|
||||||
|
inc = availableSpace.y - child->GetPosition().y;
|
||||||
|
}
|
||||||
|
|
||||||
while (node)
|
while (node)
|
||||||
{
|
{
|
||||||
@@ -2229,15 +2267,19 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, wxRichTextDrawingContext& co
|
|||||||
{
|
{
|
||||||
if (child->GetLines().GetCount() == 0)
|
if (child->GetLines().GetCount() == 0)
|
||||||
{
|
{
|
||||||
|
child->SetImpactedByFloatingObjects(-1);
|
||||||
|
|
||||||
// Lays out the object first with a given amount of space, and then if no width was specified in attr,
|
// Lays out the object first with a given amount of space, and then if no width was specified in attr,
|
||||||
// lays out the object again using the minimum size
|
// lays out the object again using the minimum size
|
||||||
child->LayoutToBestSize(dc, context, GetBuffer(),
|
child->LayoutToBestSize(dc, context, GetBuffer(),
|
||||||
attr, child->GetAttributes(), availableSpace, rect, style&~wxRICHTEXT_LAYOUT_SPECIFIED_RECT);
|
attr, child->GetAttributes(), availableSpace, rect, style&~wxRICHTEXT_LAYOUT_SPECIFIED_RECT);
|
||||||
|
|
||||||
//child->Layout(dc, availableChildRect, style);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (wxRichTextBuffer::GetFloatingLayoutMode() && GetFloatCollector())
|
||||||
|
GetFloatCollector()->CollectFloat(child);
|
||||||
child->Move(wxPoint(child->GetPosition().x, child->GetPosition().y + inc));
|
child->Move(wxPoint(child->GetPosition().x, child->GetPosition().y + inc));
|
||||||
|
}
|
||||||
|
|
||||||
availableSpace.y += child->GetCachedSize().y;
|
availableSpace.y += child->GetCachedSize().y;
|
||||||
maxWidth = wxMax(maxWidth, child->GetCachedSize().x);
|
maxWidth = wxMax(maxWidth, child->GetCachedSize().x);
|
||||||
@@ -4047,21 +4089,10 @@ wxRichTextRange wxRichTextParagraphLayoutBox::GetInvalidRange(bool wholeParagrap
|
|||||||
if (para1)
|
if (para1)
|
||||||
range.SetStart(para1->GetRange().GetStart());
|
range.SetStart(para1->GetRange().GetStart());
|
||||||
|
|
||||||
// FIXME: be more intelligent about this. Check if we have floating objects
|
|
||||||
// before the end of the range. But it's not clear how we can in general
|
|
||||||
// tell where it's safe to stop laying out.
|
|
||||||
// Anyway, this code is central to efficiency when laying in floating mode.
|
|
||||||
if (!wxRichTextBuffer::GetFloatingLayoutMode())
|
|
||||||
{
|
|
||||||
wxRichTextParagraph* para2 = GetParagraphAtPosition(range.GetEnd());
|
wxRichTextParagraph* para2 = GetParagraphAtPosition(range.GetEnd());
|
||||||
if (para2)
|
if (para2)
|
||||||
range.SetEnd(para2->GetRange().GetEnd());
|
range.SetEnd(para2->GetRange().GetEnd());
|
||||||
}
|
}
|
||||||
else
|
|
||||||
// Floating layout means that all children should be laid out,
|
|
||||||
// because we can't tell how the whole buffer will be affected.
|
|
||||||
range.SetEnd(GetOwnRange().GetEnd());
|
|
||||||
}
|
|
||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4643,6 +4674,8 @@ wxArrayInt wxRichTextParagraph::sm_defaultTabs;
|
|||||||
wxRichTextParagraph::wxRichTextParagraph(wxRichTextObject* parent, wxRichTextAttr* style):
|
wxRichTextParagraph::wxRichTextParagraph(wxRichTextObject* parent, wxRichTextAttr* style):
|
||||||
wxRichTextCompositeObject(parent)
|
wxRichTextCompositeObject(parent)
|
||||||
{
|
{
|
||||||
|
Init();
|
||||||
|
|
||||||
if (style)
|
if (style)
|
||||||
SetAttributes(*style);
|
SetAttributes(*style);
|
||||||
}
|
}
|
||||||
@@ -4650,12 +4683,19 @@ wxRichTextParagraph::wxRichTextParagraph(wxRichTextObject* parent, wxRichTextAtt
|
|||||||
wxRichTextParagraph::wxRichTextParagraph(const wxString& text, wxRichTextObject* parent, wxRichTextAttr* paraStyle, wxRichTextAttr* charStyle):
|
wxRichTextParagraph::wxRichTextParagraph(const wxString& text, wxRichTextObject* parent, wxRichTextAttr* paraStyle, wxRichTextAttr* charStyle):
|
||||||
wxRichTextCompositeObject(parent)
|
wxRichTextCompositeObject(parent)
|
||||||
{
|
{
|
||||||
|
Init();
|
||||||
|
|
||||||
if (paraStyle)
|
if (paraStyle)
|
||||||
SetAttributes(*paraStyle);
|
SetAttributes(*paraStyle);
|
||||||
|
|
||||||
AppendChild(new wxRichTextPlainText(text, this, charStyle));
|
AppendChild(new wxRichTextPlainText(text, this, charStyle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxRichTextParagraph::Init()
|
||||||
|
{
|
||||||
|
m_impactedByFloatingObjects = -1;
|
||||||
|
}
|
||||||
|
|
||||||
wxRichTextParagraph::~wxRichTextParagraph()
|
wxRichTextParagraph::~wxRichTextParagraph()
|
||||||
{
|
{
|
||||||
ClearLines();
|
ClearLines();
|
||||||
@@ -4850,14 +4890,22 @@ bool wxRichTextParagraph::Layout(wxDC& dc, wxRichTextDrawingContext& context, co
|
|||||||
{
|
{
|
||||||
wxASSERT(collector != NULL);
|
wxASSERT(collector != NULL);
|
||||||
if (collector)
|
if (collector)
|
||||||
|
{
|
||||||
|
if (m_impactedByFloatingObjects == -1)
|
||||||
|
{
|
||||||
|
if (collector->GetLastRectBottom() >= rect.GetTop())
|
||||||
|
m_impactedByFloatingObjects = 1;
|
||||||
|
else
|
||||||
|
m_impactedByFloatingObjects = 0;
|
||||||
|
}
|
||||||
|
|
||||||
LayoutFloat(dc, context, rect, parentRect, style, collector);
|
LayoutFloat(dc, context, rect, parentRect, style, collector);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wxRichTextAttr attr = GetCombinedAttributes();
|
wxRichTextAttr attr = GetCombinedAttributes();
|
||||||
AdjustAttributes(attr, context);
|
AdjustAttributes(attr, context);
|
||||||
|
|
||||||
// ClearLines();
|
|
||||||
|
|
||||||
// Increase the size of the paragraph due to spacing
|
// Increase the size of the paragraph due to spacing
|
||||||
int spaceBeforePara = ConvertTenthsMMToPixels(dc, attr.GetParagraphSpacingBefore());
|
int spaceBeforePara = ConvertTenthsMMToPixels(dc, attr.GetParagraphSpacingBefore());
|
||||||
int spaceAfterPara = ConvertTenthsMMToPixels(dc, attr.GetParagraphSpacingAfter());
|
int spaceAfterPara = ConvertTenthsMMToPixels(dc, attr.GetParagraphSpacingAfter());
|
||||||
@@ -11448,7 +11496,8 @@ wxRichTextParagraphLayoutBox* wxRichTextAction::GetContainer() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void wxRichTextAction::CalculateRefreshOptimizations(wxArrayInt& optimizationLineCharPositions, wxArrayInt& optimizationLineYPositions)
|
void wxRichTextAction::CalculateRefreshOptimizations(wxArrayInt& optimizationLineCharPositions, wxArrayInt& optimizationLineYPositions,
|
||||||
|
wxRect& oldFloatRect)
|
||||||
{
|
{
|
||||||
// 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
|
||||||
@@ -11472,7 +11521,8 @@ void wxRichTextAction::CalculateRefreshOptimizations(wxArrayInt& optimizationLin
|
|||||||
int lastY = firstVisiblePt.y + clientSize.y;
|
int lastY = firstVisiblePt.y + clientSize.y;
|
||||||
|
|
||||||
wxRichTextParagraph* para = container->GetParagraphAtPosition(GetRange().GetStart());
|
wxRichTextParagraph* para = container->GetParagraphAtPosition(GetRange().GetStart());
|
||||||
wxRichTextObjectList::compatibility_iterator node = container->GetChildren().Find(para);
|
wxRichTextObjectList::compatibility_iterator firstNode = container->GetChildren().Find(para);
|
||||||
|
wxRichTextObjectList::compatibility_iterator node = firstNode;
|
||||||
while (node)
|
while (node)
|
||||||
{
|
{
|
||||||
wxRichTextParagraph* child = (wxRichTextParagraph*) node->GetData();
|
wxRichTextParagraph* child = (wxRichTextParagraph*) node->GetData();
|
||||||
@@ -11501,6 +11551,26 @@ void wxRichTextAction::CalculateRefreshOptimizations(wxArrayInt& optimizationLin
|
|||||||
if (node)
|
if (node)
|
||||||
node = node->GetNext();
|
node = node->GetNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wxRichTextBuffer::GetFloatingLayoutMode() && container->GetFloatingObjectCount() > 0)
|
||||||
|
{
|
||||||
|
// We will use a simple criterion - if any of the paragraphs following the
|
||||||
|
// modification point are affected by floats in other paragraphs,
|
||||||
|
// then we will simply update the rest of the screen.
|
||||||
|
wxRichTextObjectList::compatibility_iterator node = firstNode;
|
||||||
|
while (node)
|
||||||
|
{
|
||||||
|
wxRichTextParagraph* child = (wxRichTextParagraph*) node->GetData();
|
||||||
|
if (child->GetRect().GetTop() > lastY)
|
||||||
|
break;
|
||||||
|
else if (child->GetImpactedByFloatingObjects() == 1)
|
||||||
|
{
|
||||||
|
oldFloatRect = wxRect(0, 0, clientSize.x, lastY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
node = node->GetNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -11522,9 +11592,10 @@ bool wxRichTextAction::Do()
|
|||||||
// we need to refresh
|
// we need to refresh
|
||||||
wxArrayInt optimizationLineCharPositions;
|
wxArrayInt optimizationLineCharPositions;
|
||||||
wxArrayInt optimizationLineYPositions;
|
wxArrayInt optimizationLineYPositions;
|
||||||
|
wxRect oldFloatRect;
|
||||||
|
|
||||||
#if wxRICHTEXT_USE_OPTIMIZED_DRAWING
|
#if wxRICHTEXT_USE_OPTIMIZED_DRAWING
|
||||||
CalculateRefreshOptimizations(optimizationLineCharPositions, optimizationLineYPositions);
|
CalculateRefreshOptimizations(optimizationLineCharPositions, optimizationLineYPositions, oldFloatRect);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
container->InsertFragment(GetRange().GetStart(), m_newParagraphs);
|
container->InsertFragment(GetRange().GetStart(), m_newParagraphs);
|
||||||
@@ -11552,7 +11623,7 @@ bool wxRichTextAction::Do()
|
|||||||
|
|
||||||
newCaretPosition = wxMin(newCaretPosition, (container->GetOwnRange().GetEnd()-1));
|
newCaretPosition = wxMin(newCaretPosition, (container->GetOwnRange().GetEnd()-1));
|
||||||
|
|
||||||
UpdateAppearance(newCaretPosition, true /* send update event */, & optimizationLineCharPositions, & optimizationLineYPositions, true /* do */);
|
UpdateAppearance(newCaretPosition, true /* send update event */, oldFloatRect, & optimizationLineCharPositions, & optimizationLineYPositions, true /* do */);
|
||||||
|
|
||||||
wxRichTextEvent cmdEvent(
|
wxRichTextEvent cmdEvent(
|
||||||
wxEVT_RICHTEXT_CONTENT_INSERTED,
|
wxEVT_RICHTEXT_CONTENT_INSERTED,
|
||||||
@@ -11570,9 +11641,10 @@ bool wxRichTextAction::Do()
|
|||||||
{
|
{
|
||||||
wxArrayInt optimizationLineCharPositions;
|
wxArrayInt optimizationLineCharPositions;
|
||||||
wxArrayInt optimizationLineYPositions;
|
wxArrayInt optimizationLineYPositions;
|
||||||
|
wxRect oldFloatRect;
|
||||||
|
|
||||||
#if wxRICHTEXT_USE_OPTIMIZED_DRAWING
|
#if wxRICHTEXT_USE_OPTIMIZED_DRAWING
|
||||||
CalculateRefreshOptimizations(optimizationLineCharPositions, optimizationLineYPositions);
|
CalculateRefreshOptimizations(optimizationLineCharPositions, optimizationLineYPositions, oldFloatRect);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Check if the current object focus needs to be changed before deletion of content
|
// Check if the current object focus needs to be changed before deletion of content
|
||||||
@@ -11600,7 +11672,7 @@ bool wxRichTextAction::Do()
|
|||||||
if (caretPos >= container->GetOwnRange().GetEnd())
|
if (caretPos >= container->GetOwnRange().GetEnd())
|
||||||
caretPos --;
|
caretPos --;
|
||||||
|
|
||||||
UpdateAppearance(caretPos, true /* send update event */, & optimizationLineCharPositions, & optimizationLineYPositions, true /* do */);
|
UpdateAppearance(caretPos, true /* send update event */, oldFloatRect, & optimizationLineCharPositions, & optimizationLineYPositions, true /* do */);
|
||||||
|
|
||||||
wxRichTextEvent cmdEvent(
|
wxRichTextEvent cmdEvent(
|
||||||
wxEVT_RICHTEXT_CONTENT_DELETED,
|
wxEVT_RICHTEXT_CONTENT_DELETED,
|
||||||
@@ -11750,9 +11822,10 @@ bool wxRichTextAction::Undo()
|
|||||||
{
|
{
|
||||||
wxArrayInt optimizationLineCharPositions;
|
wxArrayInt optimizationLineCharPositions;
|
||||||
wxArrayInt optimizationLineYPositions;
|
wxArrayInt optimizationLineYPositions;
|
||||||
|
wxRect oldFloatRect;
|
||||||
|
|
||||||
#if wxRICHTEXT_USE_OPTIMIZED_DRAWING
|
#if wxRICHTEXT_USE_OPTIMIZED_DRAWING
|
||||||
CalculateRefreshOptimizations(optimizationLineCharPositions, optimizationLineYPositions);
|
CalculateRefreshOptimizations(optimizationLineCharPositions, optimizationLineYPositions, oldFloatRect);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Check if the current object focus needs to be changed before deletion of content
|
// Check if the current object focus needs to be changed before deletion of content
|
||||||
@@ -11779,7 +11852,7 @@ bool wxRichTextAction::Undo()
|
|||||||
|
|
||||||
long newCaretPosition = GetPosition() - 1;
|
long newCaretPosition = GetPosition() - 1;
|
||||||
|
|
||||||
UpdateAppearance(newCaretPosition, true, /* send update event */ & optimizationLineCharPositions, & optimizationLineYPositions, false /* undo */);
|
UpdateAppearance(newCaretPosition, true, /* send update event */ oldFloatRect, & optimizationLineCharPositions, & optimizationLineYPositions, false /* undo */);
|
||||||
|
|
||||||
wxRichTextEvent cmdEvent(
|
wxRichTextEvent cmdEvent(
|
||||||
wxEVT_RICHTEXT_CONTENT_DELETED,
|
wxEVT_RICHTEXT_CONTENT_DELETED,
|
||||||
@@ -11797,9 +11870,10 @@ bool wxRichTextAction::Undo()
|
|||||||
{
|
{
|
||||||
wxArrayInt optimizationLineCharPositions;
|
wxArrayInt optimizationLineCharPositions;
|
||||||
wxArrayInt optimizationLineYPositions;
|
wxArrayInt optimizationLineYPositions;
|
||||||
|
wxRect oldFloatRect;
|
||||||
|
|
||||||
#if wxRICHTEXT_USE_OPTIMIZED_DRAWING
|
#if wxRICHTEXT_USE_OPTIMIZED_DRAWING
|
||||||
CalculateRefreshOptimizations(optimizationLineCharPositions, optimizationLineYPositions);
|
CalculateRefreshOptimizations(optimizationLineCharPositions, optimizationLineYPositions, oldFloatRect);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
container->InsertFragment(GetRange().GetStart(), m_oldParagraphs);
|
container->InsertFragment(GetRange().GetStart(), m_oldParagraphs);
|
||||||
@@ -11809,7 +11883,7 @@ bool wxRichTextAction::Undo()
|
|||||||
// Layout() would stop prematurely at the top level.
|
// Layout() would stop prematurely at the top level.
|
||||||
container->InvalidateHierarchy(GetRange());
|
container->InvalidateHierarchy(GetRange());
|
||||||
|
|
||||||
UpdateAppearance(GetPosition(), true, /* send update event */ & optimizationLineCharPositions, & optimizationLineYPositions, false /* undo */);
|
UpdateAppearance(GetPosition(), true, /* send update event */ oldFloatRect, & optimizationLineCharPositions, & optimizationLineYPositions, false /* undo */);
|
||||||
|
|
||||||
wxRichTextEvent cmdEvent(
|
wxRichTextEvent cmdEvent(
|
||||||
wxEVT_RICHTEXT_CONTENT_INSERTED,
|
wxEVT_RICHTEXT_CONTENT_INSERTED,
|
||||||
@@ -11858,7 +11932,7 @@ bool wxRichTextAction::Undo()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Update the control appearance
|
/// Update the control appearance
|
||||||
void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent, wxArrayInt* optimizationLineCharPositions, wxArrayInt* optimizationLineYPositions, bool isDoCmd)
|
void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent, const wxRect& oldFloatRect, wxArrayInt* optimizationLineCharPositions, wxArrayInt* optimizationLineYPositions, bool isDoCmd)
|
||||||
{
|
{
|
||||||
wxRichTextParagraphLayoutBox* container = GetContainer();
|
wxRichTextParagraphLayoutBox* container = GetContainer();
|
||||||
wxASSERT(container != NULL);
|
wxASSERT(container != NULL);
|
||||||
@@ -11878,7 +11952,8 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent
|
|||||||
|
|
||||||
// Refresh everything if there were floating objects or the container changed size
|
// Refresh everything if there were floating objects or the container changed size
|
||||||
// (we can't yet optimize in these cases, since more complex interaction with other content occurs)
|
// (we can't yet optimize in these cases, since more complex interaction with other content occurs)
|
||||||
if ((wxRichTextBuffer::GetFloatingLayoutMode() && container->GetFloatingObjectCount() > 0) || (container->GetParent() && containerRect != container->GetRect()))
|
// Refresh everything if container changed size.
|
||||||
|
if (container->GetParent() && containerRect != container->GetRect())
|
||||||
{
|
{
|
||||||
m_ctrl->Refresh(false);
|
m_ctrl->Refresh(false);
|
||||||
}
|
}
|
||||||
@@ -11892,6 +11967,7 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent
|
|||||||
|
|
||||||
wxSize clientSize = m_ctrl->GetUnscaledSize(m_ctrl->GetClientSize());
|
wxSize clientSize = m_ctrl->GetUnscaledSize(m_ctrl->GetClientSize());
|
||||||
wxPoint firstVisiblePt = m_ctrl->GetUnscaledPoint(m_ctrl->GetFirstVisiblePoint());
|
wxPoint firstVisiblePt = m_ctrl->GetUnscaledPoint(m_ctrl->GetFirstVisiblePoint());
|
||||||
|
int lastPossibleY = firstVisiblePt.y + clientSize.y;
|
||||||
|
|
||||||
// Start/end positions
|
// Start/end positions
|
||||||
int firstY = 0;
|
int firstY = 0;
|
||||||
@@ -11921,7 +11997,9 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent
|
|||||||
firstY = para->GetPosition().y - 4;
|
firstY = para->GetPosition().y - 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxRichTextObjectList::compatibility_iterator node = container->GetChildren().Find(para);
|
wxRichTextObjectList::compatibility_iterator firstNode = container->GetChildren().Find(para);
|
||||||
|
wxRichTextObjectList::compatibility_iterator node = firstNode;
|
||||||
|
wxRichTextObjectList::compatibility_iterator lastNode = NULL;
|
||||||
while (node)
|
while (node)
|
||||||
{
|
{
|
||||||
wxRichTextParagraph* child = (wxRichTextParagraph*) node->GetData();
|
wxRichTextParagraph* child = (wxRichTextParagraph*) node->GetData();
|
||||||
@@ -11950,6 +12028,8 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent
|
|||||||
lastY = pt.y + line->GetSize().y;
|
lastY = pt.y + line->GetSize().y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastNode = node;
|
||||||
|
|
||||||
node2 = wxRichTextLineList::compatibility_iterator();
|
node2 = wxRichTextLineList::compatibility_iterator();
|
||||||
node = wxRichTextObjectList::compatibility_iterator();
|
node = wxRichTextObjectList::compatibility_iterator();
|
||||||
|
|
||||||
@@ -11968,6 +12048,8 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent
|
|||||||
|
|
||||||
lastY = pt.y + line->GetSize().y;
|
lastY = pt.y + line->GetSize().y;
|
||||||
|
|
||||||
|
lastNode = node;
|
||||||
|
|
||||||
node2 = wxRichTextLineList::compatibility_iterator();
|
node2 = wxRichTextLineList::compatibility_iterator();
|
||||||
node = wxRichTextObjectList::compatibility_iterator();
|
node = wxRichTextObjectList::compatibility_iterator();
|
||||||
|
|
||||||
@@ -11988,6 +12070,32 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent
|
|||||||
if (!foundEnd)
|
if (!foundEnd)
|
||||||
lastY = firstVisiblePt.y + clientSize.y;
|
lastY = firstVisiblePt.y + clientSize.y;
|
||||||
|
|
||||||
|
if (wxRichTextBuffer::GetFloatingLayoutMode())
|
||||||
|
{
|
||||||
|
if (oldFloatRect.GetBottom() > 0)
|
||||||
|
lastY = wxMax(lastY, oldFloatRect.GetBottom());
|
||||||
|
|
||||||
|
// Now find the first paragraph that isn't affected by any floating objects,
|
||||||
|
// which means the reformatting stopped at this point.
|
||||||
|
if (lastNode && (container->GetFloatingObjectCount() > 0) && (lastY < lastPossibleY))
|
||||||
|
{
|
||||||
|
wxRichTextObjectList::compatibility_iterator node = lastNode;
|
||||||
|
while (node)
|
||||||
|
{
|
||||||
|
wxRichTextParagraph* child = (wxRichTextParagraph*) node->GetData();
|
||||||
|
if (child->GetImpactedByFloatingObjects() == 0)
|
||||||
|
{
|
||||||
|
wxRect childRect = child->GetRect();
|
||||||
|
if (childRect.GetBottom() > lastY)
|
||||||
|
lastY = wxMin(childRect.GetBottom(), lastPossibleY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = node->GetNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Convert to device coordinates
|
// Convert to device coordinates
|
||||||
wxRect rect(m_ctrl->GetPhysicalPoint(m_ctrl->GetScaledPoint(wxPoint(firstVisiblePt.x, firstY))), m_ctrl->GetScaledSize(wxSize(clientSize.x, lastY - firstY)));
|
wxRect rect(m_ctrl->GetPhysicalPoint(m_ctrl->GetScaledPoint(wxPoint(firstVisiblePt.x, firstY))), m_ctrl->GetScaledSize(wxSize(clientSize.x, lastY - firstY)));
|
||||||
m_ctrl->RefreshRect(rect);
|
m_ctrl->RefreshRect(rect);
|
||||||
@@ -12127,7 +12235,12 @@ bool wxRichTextImage::LoadImageCache(wxDC& dc, wxRichTextDrawingContext& context
|
|||||||
|
|
||||||
m_imageBlock.Load(image);
|
m_imageBlock.Load(image);
|
||||||
if (!image.IsOk())
|
if (!image.IsOk())
|
||||||
|
{
|
||||||
|
wxBitmap bitmap(image_placeholder24x24_xpm);
|
||||||
|
m_imageCache = bitmap;
|
||||||
|
m_originalImageSize = wxSize(bitmap.GetWidth(), bitmap.GetHeight());
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
m_originalImageSize = wxSize(image.GetWidth(), image.GetHeight());
|
m_originalImageSize = wxSize(image.GetWidth(), image.GetHeight());
|
||||||
}
|
}
|
||||||
@@ -12154,6 +12267,8 @@ bool wxRichTextImage::LoadImageCache(wxDC& dc, wxRichTextDrawingContext& context
|
|||||||
{
|
{
|
||||||
if (buffer)
|
if (buffer)
|
||||||
{
|
{
|
||||||
|
// Surely margins will already be accounted for?
|
||||||
|
#if 0
|
||||||
// Find the actual space available when margin is taken into account
|
// Find the actual space available when margin is taken into account
|
||||||
wxRect marginRect, borderRect, contentRect, paddingRect, outlineRect;
|
wxRect marginRect, borderRect, contentRect, paddingRect, outlineRect;
|
||||||
marginRect = wxRect(0, 0, sz.x, sz.y);
|
marginRect = wxRect(0, 0, sz.x, sz.y);
|
||||||
@@ -12162,7 +12277,7 @@ bool wxRichTextImage::LoadImageCache(wxDC& dc, wxRichTextDrawingContext& context
|
|||||||
buffer->GetBoxRects(dc, buffer, GetParent()->GetParent()->GetAttributes(), marginRect, borderRect, contentRect, paddingRect, outlineRect);
|
buffer->GetBoxRects(dc, buffer, GetParent()->GetParent()->GetAttributes(), marginRect, borderRect, contentRect, paddingRect, outlineRect);
|
||||||
sz = contentRect.GetSize();
|
sz = contentRect.GetSize();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
// Use a minimum size to stop images becoming very small
|
// Use a minimum size to stop images becoming very small
|
||||||
parentWidth = wxMax(100, sz.GetWidth());
|
parentWidth = wxMax(100, sz.GetWidth());
|
||||||
parentHeight = wxMax(100, sz.GetHeight());
|
parentHeight = wxMax(100, sz.GetHeight());
|
||||||
@@ -12245,8 +12360,13 @@ bool wxRichTextImage::LoadImageCache(wxDC& dc, wxRichTextDrawingContext& context
|
|||||||
{
|
{
|
||||||
m_imageBlock.Load(image);
|
m_imageBlock.Load(image);
|
||||||
if (!image.IsOk())
|
if (!image.IsOk())
|
||||||
|
{
|
||||||
|
wxBitmap bitmap(image_placeholder24x24_xpm);
|
||||||
|
m_imageCache = bitmap;
|
||||||
|
m_originalImageSize = wxSize(bitmap.GetWidth(), bitmap.GetHeight());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (image.GetWidth() == width && image.GetHeight() == height)
|
if (image.GetWidth() == width && image.GetHeight() == height)
|
||||||
m_imageCache = wxBitmap(image);
|
m_imageCache = wxBitmap(image);
|
||||||
@@ -12277,7 +12397,7 @@ bool wxRichTextImage::Draw(wxDC& dc, wxRichTextDrawingContext& context, const wx
|
|||||||
if (!IsShown())
|
if (!IsShown())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!LoadImageCache(dc, context))
|
if (!m_imageCache.IsOk())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
wxRichTextAttr attr(GetAttributes());
|
wxRichTextAttr attr(GetAttributes());
|
||||||
@@ -12305,9 +12425,9 @@ bool wxRichTextImage::Draw(wxDC& dc, wxRichTextDrawingContext& context, const wx
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Lay the item out
|
/// Lay the item out
|
||||||
bool wxRichTextImage::Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& WXUNUSED(parentRect), int WXUNUSED(style))
|
bool wxRichTextImage::Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int WXUNUSED(style))
|
||||||
{
|
{
|
||||||
if (!LoadImageCache(dc, context))
|
if (!LoadImageCache(dc, context, false, parentRect.GetSize()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
wxSize imageSize(m_imageCache.GetWidth(), m_imageCache.GetHeight());
|
wxSize imageSize(m_imageCache.GetWidth(), m_imageCache.GetHeight());
|
||||||
|
Reference in New Issue
Block a user