X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4dc7ae1ae8af4415c54a4fe949ebd7f3489293b9..662ba874795045558374a61c85a7e3c2de5bbdbb:/src/richtext/richtextbuffer.cpp diff --git a/src/richtext/richtextbuffer.cpp b/src/richtext/richtextbuffer.cpp index ce0f18c004..5881f6f45c 100644 --- a/src/richtext/richtextbuffer.cpp +++ b/src/richtext/richtextbuffer.cpp @@ -105,10 +105,10 @@ public: int GetLastRectBottom(); // Draw the floats inside a rect - void Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); + void Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); // HitTest the floats - int HitTest(wxDC& dc, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, int flags); + int HitTest(wxDC& dc, wxRichTextDrawingContext& context, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, int flags); // Get floating object count int GetFloatingObjectCount() const { return m_left.GetCount() + m_right.GetCount(); } @@ -130,9 +130,9 @@ public: static void FreeFloatRectMapArray(wxRichTextFloatRectMapArray& array); - static void DrawFloat(const wxRichTextFloatRectMapArray& array, wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); + static void DrawFloat(const wxRichTextFloatRectMapArray& array, wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); - static int HitTestFloat(const wxRichTextFloatRectMapArray& array, wxDC& WXUNUSED(dc), const wxPoint& pt, long& textPosition, wxRichTextObject** obj, int flags); + static int HitTestFloat(const wxRichTextFloatRectMapArray& array, wxDC& dc, wxRichTextDrawingContext& context, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, int flags); private: wxRichTextFloatRectMapArray m_left; @@ -396,7 +396,7 @@ int wxRichTextFloatCollector::GetLastRectBottom() return ret; } -void wxRichTextFloatCollector::DrawFloat(const wxRichTextFloatRectMapArray& array, wxDC& dc, const wxRichTextRange& WXUNUSED(range), const wxRichTextSelection& selection, const wxRect& rect, int descent, int style) +void wxRichTextFloatCollector::DrawFloat(const wxRichTextFloatRectMapArray& array, wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& WXUNUSED(range), const wxRichTextSelection& selection, const wxRect& rect, int descent, int style) { int start = rect.y; int end = rect.y + rect.height; @@ -411,20 +411,20 @@ void wxRichTextFloatCollector::DrawFloat(const wxRichTextFloatRectMapArray& arra { wxRichTextObject* obj = array[i]->anchor; wxRichTextRange r = obj->GetRange(); - obj->Draw(dc, r, selection, wxRect(obj->GetPosition(), obj->GetCachedSize()), descent, style); + obj->Draw(dc, context, r, selection, wxRect(obj->GetPosition(), obj->GetCachedSize()), descent, style); i++; } } -void wxRichTextFloatCollector::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style) +void wxRichTextFloatCollector::Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style) { if (m_left.GetCount() > 0) - DrawFloat(m_left, dc, range, selection, rect, descent, style); + DrawFloat(m_left, dc, context, range, selection, rect, descent, style); if (m_right.GetCount() > 0) - DrawFloat(m_right, dc, range, selection, rect, descent, style); + DrawFloat(m_right, dc, context, range, selection, rect, descent, style); } -int wxRichTextFloatCollector::HitTestFloat(const wxRichTextFloatRectMapArray& array, wxDC& WXUNUSED(dc), const wxPoint& pt, long& textPosition, wxRichTextObject** obj, int WXUNUSED(flags)) +int wxRichTextFloatCollector::HitTestFloat(const wxRichTextFloatRectMapArray& array, wxDC& WXUNUSED(dc), wxRichTextDrawingContext& WXUNUSED(context), const wxPoint& pt, long& textPosition, wxRichTextObject** obj, int WXUNUSED(flags)) { int i; if (array.GetCount() == 0) @@ -451,12 +451,12 @@ int wxRichTextFloatCollector::HitTestFloat(const wxRichTextFloatRectMapArray& ar return wxRICHTEXT_HITTEST_NONE; } -int wxRichTextFloatCollector::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, int flags) +int wxRichTextFloatCollector::HitTest(wxDC& dc, wxRichTextDrawingContext& context, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, int flags) { - int ret = HitTestFloat(m_left, dc, pt, textPosition, obj, flags); + int ret = HitTestFloat(m_left, dc, context, pt, textPosition, obj, flags); if (ret == wxRICHTEXT_HITTEST_NONE) { - ret = HitTestFloat(m_right, dc, pt, textPosition, obj, flags); + ret = HitTestFloat(m_right, dc, context, pt, textPosition, obj, flags); } return ret; } @@ -598,11 +598,13 @@ int wxRichTextObject::GetBottomMargin() const // Calculate the available content space in the given rectangle, given the // margins, border and padding specified in the object's attributes. -wxRect wxRichTextObject::GetAvailableContentArea(wxDC& dc, const wxRect& outerRect) const +wxRect wxRichTextObject::GetAvailableContentArea(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& outerRect) const { wxRect marginRect, borderRect, contentRect, paddingRect, outlineRect; marginRect = outerRect; - GetBoxRects(dc, GetBuffer(), GetAttributes(), marginRect, borderRect, contentRect, paddingRect, outlineRect); + wxRichTextAttr attr(GetAttributes()); + context.ApplyVirtualAttributes(attr, (wxRichTextObject*) this); + GetBoxRects(dc, GetBuffer(), attr, marginRect, borderRect, contentRect, paddingRect, outlineRect); return contentRect; } @@ -696,7 +698,7 @@ bool wxRichTextObject::DrawBoxAttributes(wxDC& dc, wxRichTextBuffer* buffer, con dc.SetPen(pen); dc.SetBrush(brush); - dc.DrawRectangle(marginRect); + dc.DrawRectangle(borderRect); } if (flags & wxRICHTEXT_DRAW_GUIDELINES) @@ -778,7 +780,7 @@ bool wxRichTextObject::DrawBorder(wxDC& dc, wxRichTextBuffer* buffer, const wxTe wxBrush brush(col); dc.SetPen(pen); dc.SetBrush(brush); - dc.DrawRectangle(rect.x - borderRight, rect.y, borderRight, rect.height); + dc.DrawRectangle(rect.x + rect.width - borderRight, rect.y, borderRight, rect.height); } } @@ -835,7 +837,7 @@ bool wxRichTextObject::DrawBorder(wxDC& dc, wxRichTextBuffer* buffer, const wxTe wxBrush brush(col); dc.SetPen(pen); dc.SetBrush(brush); - dc.DrawRectangle(rect.x, rect.y - rect.height - borderBottom, rect.width, borderBottom); + dc.DrawRectangle(rect.x, rect.y + rect.height - borderBottom, rect.width, borderBottom); } } @@ -864,7 +866,7 @@ bool wxRichTextObject::GetBoxRects(wxDC& dc, wxRichTextBuffer* buffer, const wxR marginRight = converter.GetPixels(attr.GetTextBoxAttr().GetMargins().GetRight()); if (attr.GetTextBoxAttr().GetMargins().GetTop().IsValid()) marginTop = converter.GetPixels(attr.GetTextBoxAttr().GetMargins().GetTop()); - if (attr.GetTextBoxAttr().GetMargins().GetLeft().IsValid()) + if (attr.GetTextBoxAttr().GetMargins().GetBottom().IsValid()) marginBottom = converter.GetPixels(attr.GetTextBoxAttr().GetMargins().GetBottom()); if (attr.GetTextBoxAttr().GetBorder().GetLeft().GetWidth().IsValid()) @@ -873,7 +875,7 @@ bool wxRichTextObject::GetBoxRects(wxDC& dc, wxRichTextBuffer* buffer, const wxR borderRight = converter.GetPixels(attr.GetTextBoxAttr().GetBorder().GetRight().GetWidth()); if (attr.GetTextBoxAttr().GetBorder().GetTop().GetWidth().IsValid()) borderTop = converter.GetPixels(attr.GetTextBoxAttr().GetBorder().GetTop().GetWidth()); - if (attr.GetTextBoxAttr().GetBorder().GetLeft().GetWidth().IsValid()) + if (attr.GetTextBoxAttr().GetBorder().GetBottom().GetWidth().IsValid()) borderBottom = converter.GetPixels(attr.GetTextBoxAttr().GetBorder().GetBottom().GetWidth()); if (attr.GetTextBoxAttr().GetPadding().GetLeft().IsValid()) @@ -953,14 +955,16 @@ bool wxRichTextObject::GetTotalMargin(wxDC& dc, wxRichTextBuffer* buffer, const // Returns the rectangle which the child has available to it given restrictions specified in the // child attribute, e.g. 50% width of the parent, 400 pixels, x position 20% of the parent, etc. -wxRect wxRichTextObject::AdjustAvailableSpace(wxDC& dc, wxRichTextBuffer* buffer, const wxRichTextAttr& WXUNUSED(parentAttr), const wxRichTextAttr& childAttr, const wxRect& availableParentSpace) +// availableContainerSpace might be a parent that the cell has to compute its width relative to. +// E.g. a cell that's 50% of its parent. +wxRect wxRichTextObject::AdjustAvailableSpace(wxDC& dc, wxRichTextBuffer* buffer, const wxRichTextAttr& WXUNUSED(parentAttr), const wxRichTextAttr& childAttr, const wxRect& availableParentSpace, const wxRect& availableContainerSpace) { wxRect rect = availableParentSpace; double scale = 1.0; if (buffer) scale = buffer->GetScale(); - wxTextAttrDimensionConverter converter(dc, scale, availableParentSpace.GetSize()); + wxTextAttrDimensionConverter converter(dc, scale, availableContainerSpace.GetSize()); if (childAttr.GetTextBoxAttr().GetWidth().IsValid()) rect.width = converter.GetPixels(childAttr.GetTextBoxAttr().GetWidth()); @@ -978,7 +982,7 @@ wxRect wxRichTextObject::AdjustAvailableSpace(wxDC& dc, wxRichTextBuffer* buffer { int x = converter.GetPixels(childAttr.GetTextBoxAttr().GetPosition().GetRight()); if (childAttr.GetTextBoxAttr().GetPosition().GetRight().GetPosition() == wxTEXT_BOX_ATTR_POSITION_RELATIVE) - rect.x = availableParentSpace.x + availableParentSpace.width - rect.width; + rect.x = availableContainerSpace.x + availableContainerSpace.width - rect.width; else rect.x += x; } @@ -991,11 +995,14 @@ wxRect wxRichTextObject::AdjustAvailableSpace(wxDC& dc, wxRichTextBuffer* buffer { int y = converter.GetPixels(childAttr.GetTextBoxAttr().GetPosition().GetBottom()); if (childAttr.GetTextBoxAttr().GetPosition().GetBottom().GetPosition() == wxTEXT_BOX_ATTR_POSITION_RELATIVE) - rect.y = availableParentSpace.y + availableParentSpace.height - rect.height; + rect.y = availableContainerSpace.y + availableContainerSpace.height - rect.height; else rect.y += y; } + if (rect.GetWidth() > availableParentSpace.GetWidth()) + rect.SetWidth(availableParentSpace.GetWidth()); + return rect; } @@ -1033,7 +1040,7 @@ wxPoint wxRichTextObject::GetAbsolutePosition() const // Hit-testing: returns a flag indicating hit test details, plus // information about position -int wxRichTextObject::HitTest(wxDC& WXUNUSED(dc), const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int WXUNUSED(flags)) +int wxRichTextObject::HitTest(wxDC& WXUNUSED(dc), wxRichTextDrawingContext& WXUNUSED(context), const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int WXUNUSED(flags)) { if (!IsShown()) return wxRICHTEXT_HITTEST_NONE; @@ -1053,19 +1060,20 @@ int wxRichTextObject::HitTest(wxDC& WXUNUSED(dc), const wxPoint& pt, long& textP // 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 maximum ('best') size -bool wxRichTextObject::LayoutToBestSize(wxDC& dc, wxRichTextBuffer* buffer, - const wxRichTextAttr& parentAttr, const wxRichTextAttr& attr, const wxRect& availableParentSpace, +bool wxRichTextObject::LayoutToBestSize(wxDC& dc, wxRichTextDrawingContext& context, wxRichTextBuffer* buffer, + const wxRichTextAttr& parentAttr, const wxRichTextAttr& attr, + const wxRect& availableParentSpace, const wxRect& availableContainerSpace, int style) { - wxRect availableChildRect = AdjustAvailableSpace(dc, buffer, parentAttr, attr, availableParentSpace); + wxRect availableChildRect = AdjustAvailableSpace(dc, buffer, parentAttr, attr, availableParentSpace, availableContainerSpace); wxRect originalAvailableRect = availableChildRect; - Layout(dc, availableChildRect, style); + Layout(dc, context, availableChildRect, availableContainerSpace, style); wxSize maxSize = GetMaxSize(); // Don't ignore if maxSize.x is zero, since we need to redo the paragraph's lines // on this basis - if (!attr.GetTextBoxAttr().GetWidth().IsValid() && maxSize.x < availableChildRect.width /* && maxSize.x > 0 */) + if (!attr.GetTextBoxAttr().GetWidth().IsValid() && maxSize.x < availableChildRect.width) { // Redo the layout with a fixed, minimum size this time. Invalidate(wxRICHTEXT_ALL); @@ -1073,7 +1081,7 @@ bool wxRichTextObject::LayoutToBestSize(wxDC& dc, wxRichTextBuffer* buffer, newAttr.GetTextBoxAttr().GetWidth().SetValue(maxSize.x, wxTEXT_ATTR_UNITS_PIXELS); newAttr.GetTextBoxAttr().GetWidth().SetPosition(wxTEXT_BOX_ATTR_POSITION_ABSOLUTE); - availableChildRect = AdjustAvailableSpace(dc, buffer, parentAttr, newAttr, availableParentSpace); + availableChildRect = AdjustAvailableSpace(dc, buffer, parentAttr, newAttr, availableParentSpace, availableContainerSpace); // If a paragraph, align the whole paragraph. // Problem with this: if we're limited by a floating object, a line may be centered @@ -1081,17 +1089,17 @@ bool wxRichTextObject::LayoutToBestSize(wxDC& dc, wxRichTextBuffer* buffer, if (attr.HasAlignment() && !GetContainer()->GetFloatCollector()->HasFloats()) // FIXME: aligning whole paragraph not compatible with floating objects { // centering, right-justification - if (GetAttributes().GetAlignment() == wxTEXT_ALIGNMENT_CENTRE) + if (attr.GetAlignment() == wxTEXT_ALIGNMENT_CENTRE) { availableChildRect.x = (originalAvailableRect.GetWidth() - availableChildRect.GetWidth())/2 + availableChildRect.x; } - else if (GetAttributes().GetAlignment() == wxTEXT_ALIGNMENT_RIGHT) + else if (attr.GetAlignment() == wxTEXT_ALIGNMENT_RIGHT) { availableChildRect.x = availableChildRect.x + originalAvailableRect.GetWidth() - availableChildRect.GetWidth(); } } - Layout(dc, availableChildRect, style); + Layout(dc, context, availableChildRect, availableContainerSpace, style); } /* @@ -1221,7 +1229,7 @@ void wxRichTextCompositeObject::Copy(const wxRichTextCompositeObject& obj) /// Hit-testing: returns a flag indicating hit test details, plus /// information about position -int wxRichTextCompositeObject::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags) +int wxRichTextCompositeObject::HitTest(wxDC& dc, wxRichTextDrawingContext& context, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags) { if (!IsShown()) return wxRICHTEXT_HITTEST_NONE; @@ -1234,13 +1242,13 @@ int wxRichTextCompositeObject::HitTest(wxDC& dc, const wxPoint& pt, long& textPo if (child->IsShown() && child->IsTopLevel() && (flags & wxRICHTEXT_HITTEST_NO_NESTED_OBJECTS)) { // Just check if we hit the overall object - int ret = child->wxRichTextObject::HitTest(dc, pt, textPosition, obj, contextObj, flags); + int ret = child->wxRichTextObject::HitTest(dc, context, pt, textPosition, obj, contextObj, flags); if (ret != wxRICHTEXT_HITTEST_NONE) return ret; } else if (child->IsShown()) { - int ret = child->HitTest(dc, pt, textPosition, obj, contextObj, flags); + int ret = child->HitTest(dc, context, pt, textPosition, obj, contextObj, flags); if (ret != wxRICHTEXT_HITTEST_NONE) return ret; } @@ -1252,7 +1260,7 @@ int wxRichTextCompositeObject::HitTest(wxDC& dc, const wxPoint& pt, long& textPo } /// Finds the absolute position and row height for the given character position -bool wxRichTextCompositeObject::FindPosition(wxDC& dc, long index, wxPoint& pt, int* height, bool forceLineStart) +bool wxRichTextCompositeObject::FindPosition(wxDC& dc, wxRichTextDrawingContext& context, long index, wxPoint& pt, int* height, bool forceLineStart) { wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst(); while (node) @@ -1263,7 +1271,7 @@ bool wxRichTextCompositeObject::FindPosition(wxDC& dc, long index, wxPoint& pt, // such as a text box, because the character position will no longer // apply. By definition, a top-level object has its own range of // character positions. - if (!child->IsTopLevel() && child->FindPosition(dc, index, pt, height, forceLineStart)) + if (!child->IsTopLevel() && child->FindPosition(dc, context, index, pt, height, forceLineStart)) return true; node = node->GetNext(); @@ -1473,7 +1481,7 @@ void wxRichTextCompositeObject::Dump(wxTextOutputStream& stream) /// Get/set the object size for the given range. Returns false if the range /// is invalid for this object. -bool wxRichTextCompositeObject::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position, wxArrayInt* partialExtents) const +bool wxRichTextCompositeObject::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int flags, wxPoint position, wxArrayInt* partialExtents) const { if (!range.IsWithin(GetRange())) return false; @@ -1529,7 +1537,7 @@ bool wxRichTextCompositeObject::GetRangeSize(const wxRichTextRange& range, wxSiz sz.x += childSize.x; descent = wxMax(descent, childDescent); } - else if (child->GetRangeSize(rangeToUse, childSize, childDescent, dc, flags, wxPoint(position.x + sz.x, position.y), p)) + else if (child->GetRangeSize(rangeToUse, childSize, childDescent, dc, context, flags, wxPoint(position.x + sz.x, position.y), p)) { sz.y = wxMax(sz.y, childSize.y); sz.x += childSize.x; @@ -1730,17 +1738,17 @@ void wxRichTextParagraphLayoutBox::UpdateRanges() } // HitTest -int wxRichTextParagraphLayoutBox::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags) +int wxRichTextParagraphLayoutBox::HitTest(wxDC& dc, wxRichTextDrawingContext& context, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags) { if (!IsShown()) return wxRICHTEXT_HITTEST_NONE; int ret = wxRICHTEXT_HITTEST_NONE; if (m_floatCollector && (flags & wxRICHTEXT_HITTEST_NO_FLOATING_OBJECTS) == 0) - ret = m_floatCollector->HitTest(dc, pt, textPosition, obj, flags); + ret = m_floatCollector->HitTest(dc, context, pt, textPosition, obj, flags); if (ret == wxRICHTEXT_HITTEST_NONE) - return wxRichTextCompositeObject::HitTest(dc, pt, textPosition, obj, contextObj, flags); + return wxRichTextCompositeObject::HitTest(dc, context, pt, textPosition, obj, contextObj, flags); else { *contextObj = this; @@ -1749,10 +1757,10 @@ int wxRichTextParagraphLayoutBox::HitTest(wxDC& dc, const wxPoint& pt, long& tex } /// Draw the floating objects -void wxRichTextParagraphLayoutBox::DrawFloats(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style) +void wxRichTextParagraphLayoutBox::DrawFloats(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style) { if (m_floatCollector) - m_floatCollector->Draw(dc, range, selection, rect, descent, style); + m_floatCollector->Draw(dc, context, range, selection, rect, descent, style); } void wxRichTextParagraphLayoutBox::MoveAnchoredObjectToParagraph(wxRichTextParagraph* from, wxRichTextParagraph* to, wxRichTextObject* obj) @@ -1765,13 +1773,16 @@ void wxRichTextParagraphLayoutBox::MoveAnchoredObjectToParagraph(wxRichTextParag } /// Draw the item -bool wxRichTextParagraphLayoutBox::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style) +bool wxRichTextParagraphLayoutBox::Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style) { if (!IsShown()) return true; wxRect thisRect(GetPosition(), GetCachedSize()); + wxRichTextAttr attr(GetAttributes()); + context.ApplyVirtualAttributes(attr, this); + int flags = style; if (selection.IsValid() && GetParentContainer() != this && selection.WithinSelection(GetRange().GetStart(), GetParentContainer())) flags |= wxRICHTEXT_DRAW_SELECTED; @@ -1780,9 +1791,9 @@ bool wxRichTextParagraphLayoutBox::Draw(wxDC& dc, const wxRichTextRange& range, int theseFlags = flags; if (!GetParent()) theseFlags &= ~wxRICHTEXT_DRAW_GUIDELINES; - DrawBoxAttributes(dc, GetBuffer(), GetAttributes(), thisRect, theseFlags); + DrawBoxAttributes(dc, GetBuffer(), attr, thisRect, theseFlags); - DrawFloats(dc, range, selection, rect, descent, style); + DrawFloats(dc, context, range, selection, rect, descent, style); wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst(); while (node) { @@ -1807,7 +1818,7 @@ bool wxRichTextParagraphLayoutBox::Draw(wxDC& dc, const wxRichTextRange& range, // Skip } else - child->Draw(dc, childRange, selection, rect, descent, style); + child->Draw(dc, context, childRange, selection, rect, descent, style); } node = node->GetNext(); @@ -1816,7 +1827,7 @@ bool wxRichTextParagraphLayoutBox::Draw(wxDC& dc, const wxRichTextRange& range, } /// Lay the item out -bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int style) +bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style) { SetPosition(rect.GetPosition()); @@ -1826,6 +1837,9 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl wxRect availableSpace; bool formatRect = (style & wxRICHTEXT_LAYOUT_SPECIFIED_RECT) == wxRICHTEXT_LAYOUT_SPECIFIED_RECT; + wxRichTextAttr attr(GetAttributes()); + context.ApplyVirtualAttributes(attr, this); + // If only laying out a specific area, the passed rect has a different meaning: // the visible part of the buffer. This is used in wxRichTextCtrl::OnSize, // so that during a size, only the visible part will be relaid out, or @@ -1834,7 +1848,7 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl if (formatRect) { wxRect rect2(0, 0, rect.width, rect.height); - availableSpace = GetAvailableContentArea(dc, rect2); + availableSpace = GetAvailableContentArea(dc, context, rect2); // Invalidate the part of the buffer from the first visible line // to the end. If other parts of the buffer are currently invalid, @@ -1849,11 +1863,11 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl } else { - availableSpace = GetAvailableContentArea(dc, rect); + availableSpace = GetAvailableContentArea(dc, context, rect); } int leftMargin, rightMargin, topMargin, bottomMargin; - wxRichTextObject::GetTotalMargin(dc, GetBuffer(), GetAttributes(), leftMargin, rightMargin, + wxRichTextObject::GetTotalMargin(dc, GetBuffer(), attr, leftMargin, rightMargin, topMargin, bottomMargin); int maxWidth = 0; @@ -1866,8 +1880,8 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl int maxMinWidth = 0; // If we have vertical alignment, we must recalculate everything. - bool hasVerticalAlignment = (GetAttributes().GetTextBoxAttr().HasVerticalAlignment() && - (GetAttributes().GetTextBoxAttr().GetVerticalAlignment() > wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP)); + bool hasVerticalAlignment = (attr.GetTextBoxAttr().HasVerticalAlignment() && + (attr.GetTextBoxAttr().GetVerticalAlignment() > wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP)); wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst(); @@ -1914,6 +1928,20 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl // A way to force speedy rest-of-buffer layout (the 'else' below) bool forceQuickLayout = false; + // First get the size of the paragraphs we won't be laying out + wxRichTextObjectList::compatibility_iterator n = m_children.GetFirst(); + while (n && n != node) + { + wxRichTextParagraph* child = wxDynamicCast(n->GetData(), wxRichTextParagraph); + if (child) + { + maxWidth = wxMax(maxWidth, child->GetCachedSize().x); + maxMinWidth = wxMax(maxMinWidth, child->GetMinSize().x); + maxMaxWidth = wxMax(maxMaxWidth, child->GetMaxSize().x); + } + n = n->GetNext(); + } + while (node) { // Assume this box only contains paragraphs @@ -1932,8 +1960,8 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl { // 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 - child->LayoutToBestSize(dc, GetBuffer(), - GetAttributes(), child->GetAttributes(), availableSpace, style&~wxRICHTEXT_LAYOUT_SPECIFIED_RECT); + child->LayoutToBestSize(dc, context, GetBuffer(), + attr, child->GetAttributes(), availableSpace, rect, style&~wxRICHTEXT_LAYOUT_SPECIFIED_RECT); // Layout must set the cached size availableSpace.y += child->GetCachedSize().y; @@ -1966,8 +1994,8 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl { // 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 - child->LayoutToBestSize(dc, GetBuffer(), - GetAttributes(), child->GetAttributes(), availableSpace, style&~wxRICHTEXT_LAYOUT_SPECIFIED_RECT); + child->LayoutToBestSize(dc, context, GetBuffer(), + attr, child->GetAttributes(), availableSpace, rect, style&~wxRICHTEXT_LAYOUT_SPECIFIED_RECT); //child->Layout(dc, availableChildRect, style); } @@ -1993,12 +2021,22 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl if (node && node->GetData()->IsShown()) { wxRichTextObject* child = node->GetData(); - // maxHeight = (child->GetPosition().y - GetPosition().y) + child->GetCachedSize().y; maxHeight = child->GetPosition().y - (GetPosition().y + topMargin) + child->GetCachedSize().y; } else maxHeight = 0; // topMargin + bottomMargin; + if (attr.GetTextBoxAttr().GetSize().GetWidth().IsValid()) + { + wxRect r = AdjustAvailableSpace(dc, GetBuffer(), wxRichTextAttr() /* not used */, attr, parentRect, parentRect); + int w = r.GetWidth(); + + // Convert external to content rect + w = w - leftMargin - rightMargin; + maxWidth = wxMax(maxWidth, w); + maxMaxWidth = wxMax(maxMaxWidth, w); + } + // TODO: (also in para layout) should set the // object's size to an absolute one if specified, // but if not specified, calculate it from content. @@ -2007,7 +2045,7 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl { wxRect marginRect, borderRect, contentRect, paddingRect, outlineRect; contentRect = wxRect(wxPoint(0, 0), wxSize(maxWidth, maxHeight)); - GetBoxRects(dc, GetBuffer(), GetAttributes(), marginRect, borderRect, contentRect, paddingRect, outlineRect); + GetBoxRects(dc, GetBuffer(), attr, marginRect, borderRect, contentRect, paddingRect, outlineRect); SetCachedSize(marginRect.GetSize()); } @@ -2015,7 +2053,7 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl { wxRect marginRect, borderRect, contentRect, paddingRect, outlineRect; contentRect = wxRect(wxPoint(0, 0), wxSize(maxMaxWidth, maxHeight)); // Actually max height is a lie, we can't know it - GetBoxRects(dc, GetBuffer(), GetAttributes(), marginRect, borderRect, contentRect, paddingRect, outlineRect); + GetBoxRects(dc, GetBuffer(), attr, marginRect, borderRect, contentRect, paddingRect, outlineRect); SetMaxSize(marginRect.GetSize()); } @@ -2023,22 +2061,22 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl { wxRect marginRect, borderRect, contentRect, paddingRect, outlineRect; contentRect = wxRect(wxPoint(0, 0), wxSize(maxMinWidth, maxHeight)); // Actually max height is a lie, we can't know it - GetBoxRects(dc, GetBuffer(), GetAttributes(), marginRect, borderRect, contentRect, paddingRect, outlineRect); + GetBoxRects(dc, GetBuffer(), attr, marginRect, borderRect, contentRect, paddingRect, outlineRect); SetMinSize(marginRect.GetSize()); } - if (GetAttributes().GetTextBoxAttr().HasVerticalAlignment() && - (GetAttributes().GetTextBoxAttr().GetVerticalAlignment() > wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP)) + if (attr.GetTextBoxAttr().HasVerticalAlignment() && + (attr.GetTextBoxAttr().GetVerticalAlignment() > wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP)) { int yOffset = 0; int leftOverSpace = availableSpace.height - topMargin - bottomMargin - maxHeight; if (leftOverSpace > 0) { - if (GetAttributes().GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_CENTRE) + if (attr.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_CENTRE) { yOffset = (leftOverSpace/2); } - else if (GetAttributes().GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_BOTTOM) + else if (attr.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_BOTTOM) { yOffset = leftOverSpace; } @@ -2066,7 +2104,7 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl } /// Get/set the size for the given range. -bool wxRichTextParagraphLayoutBox::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position, wxArrayInt* WXUNUSED(partialExtents)) const +bool wxRichTextParagraphLayoutBox::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int flags, wxPoint position, wxArrayInt* WXUNUSED(partialExtents)) const { wxSize sz; @@ -2125,7 +2163,7 @@ bool wxRichTextParagraphLayoutBox::GetRangeSize(const wxRichTextRange& range, wx wxSize childSize; int childDescent = 0; - child->GetRangeSize(rangeToFind, childSize, childDescent, dc, flags, position); + child->GetRangeSize(rangeToFind, childSize, childDescent, dc, context, flags, position); descent = wxMax(childDescent, descent); @@ -2676,7 +2714,7 @@ bool wxRichTextParagraphLayoutBox::CopyFragment(const wxRichTextRange& range, wx topTailRange.SetEnd(fragment.GetOwnRange().GetEnd()); } - if (topTailRange.GetStart() < (lastPara->GetRange().GetEnd()-1)) + if (topTailRange.GetStart() < lastPara->GetRange().GetEnd()) { lastPara->DeleteRange(topTailRange); @@ -3486,6 +3524,171 @@ bool wxRichTextParagraphLayoutBox::HasParagraphAttributes(const wxRichTextRange& return foundCount == matchingCount && foundCount != 0; } +void wxRichTextParagraphLayoutBox::PrepareContent(wxRichTextParagraphLayoutBox& container) +{ + wxRichTextBuffer* buffer = GetBuffer(); + if (buffer && buffer->GetRichTextCtrl()) + buffer->GetRichTextCtrl()->PrepareContent(container); +} + + +/// Set character or paragraph properties +bool wxRichTextParagraphLayoutBox::SetProperties(const wxRichTextRange& range, const wxRichTextProperties& properties, int flags) +{ + wxRichTextBuffer* buffer = GetBuffer(); + + bool withUndo = ((flags & wxRICHTEXT_SETPROPERTIES_WITH_UNDO) != 0); + bool parasOnly = ((flags & wxRICHTEXT_SETPROPERTIES_PARAGRAPHS_ONLY) != 0); + bool charactersOnly = ((flags & wxRICHTEXT_SETPROPERTIES_CHARACTERS_ONLY) != 0); + bool resetExistingProperties = ((flags & wxRICHTEXT_SETPROPERTIES_RESET) != 0); + bool removeProperties = ((flags & wxRICHTEXT_SETPROPERTIES_REMOVE) != 0); + + // If we are associated with a control, make undoable; otherwise, apply immediately + // to the data. + + bool haveControl = (buffer->GetRichTextCtrl() != NULL); + + wxRichTextAction* action = NULL; + + if (haveControl && withUndo) + { + action = new wxRichTextAction(NULL, _("Change Properties"), wxRICHTEXT_CHANGE_PROPERTIES, buffer, this, buffer->GetRichTextCtrl()); + action->SetRange(range); + action->SetPosition(buffer->GetRichTextCtrl()->GetCaretPosition()); + } + + wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst(); + while (node) + { + wxRichTextParagraph* para = wxDynamicCast(node->GetData(), wxRichTextParagraph); + // wxASSERT (para != NULL); + + if (para && para->GetChildCount() > 0) + { + // Stop searching if we're beyond the range of interest + if (para->GetRange().GetStart() > range.GetEnd()) + break; + + if (!para->GetRange().IsOutside(range)) + { + // We'll be using a copy of the paragraph to make style changes, + // not updating the buffer directly. + wxRichTextParagraph* newPara wxDUMMY_INITIALIZE(NULL); + + if (haveControl && withUndo) + { + newPara = new wxRichTextParagraph(*para); + action->GetNewParagraphs().AppendChild(newPara); + + // Also store the old ones for Undo + action->GetOldParagraphs().AppendChild(new wxRichTextParagraph(*para)); + } + else + newPara = para; + + if (parasOnly) + { + if (removeProperties) + { + // Removes the given style from the paragraph + // TODO + newPara->GetProperties().RemoveProperties(properties); + } + else if (resetExistingProperties) + newPara->GetProperties() = properties; + else + newPara->GetProperties().MergeProperties(properties); + } + + // When applying paragraph styles dynamically, don't change the text objects' attributes + // since they will computed as needed. Only apply the character styling if it's _only_ + // character styling. This policy is subject to change and might be put under user control. + + // Hm. we might well be applying a mix of paragraph and character styles, in which + // case we _do_ want to apply character styles regardless of what para styles are set. + // But if we're applying a paragraph style, which has some character attributes, but + // we only want the paragraphs to hold this character style, then we _don't_ want to + // apply the character style. So we need to be able to choose. + + if (!parasOnly && charactersOnly && range.GetStart() != newPara->GetRange().GetEnd()) + { + wxRichTextRange childRange(range); + childRange.LimitTo(newPara->GetRange()); + + // Find the starting position and if necessary split it so + // we can start applying different properties. + // TODO: check that the properties actually change or are different + // from properties outside of range + wxRichTextObject* firstObject wxDUMMY_INITIALIZE(NULL); + wxRichTextObject* lastObject wxDUMMY_INITIALIZE(NULL); + + if (childRange.GetStart() == newPara->GetRange().GetStart()) + firstObject = newPara->GetChildren().GetFirst()->GetData(); + else + firstObject = newPara->SplitAt(range.GetStart()); + + // Increment by 1 because we're apply the style one _after_ the split point + long splitPoint = childRange.GetEnd(); + if (splitPoint != newPara->GetRange().GetEnd()) + splitPoint ++; + + // Find last object + if (splitPoint == newPara->GetRange().GetEnd()) + lastObject = newPara->GetChildren().GetLast()->GetData(); + else + // lastObject is set as a side-effect of splitting. It's + // returned as the object before the new object. + (void) newPara->SplitAt(splitPoint, & lastObject); + + wxASSERT(firstObject != NULL); + wxASSERT(lastObject != NULL); + + if (!firstObject || !lastObject) + continue; + + wxRichTextObjectList::compatibility_iterator firstNode = newPara->GetChildren().Find(firstObject); + wxRichTextObjectList::compatibility_iterator lastNode = newPara->GetChildren().Find(lastObject); + + wxASSERT(firstNode); + wxASSERT(lastNode); + + wxRichTextObjectList::compatibility_iterator node2 = firstNode; + + while (node2) + { + wxRichTextObject* child = node2->GetData(); + + if (removeProperties) + { + // Removes the given properties from the paragraph + child->GetProperties().RemoveProperties(properties); + } + else if (resetExistingProperties) + child->GetProperties() = properties; + else + { + child->GetProperties().MergeProperties(properties); + } + + if (node2 == lastNode) + break; + + node2 = node2->GetNext(); + } + } + } + } + + node = node->GetNext(); + } + + // Do action, or delay it until end of batch. + if (haveControl && withUndo) + buffer->SubmitAction(action); + + return true; +} + void wxRichTextParagraphLayoutBox::Reset() { Clear(); @@ -3502,6 +3705,8 @@ void wxRichTextParagraphLayoutBox::Reset() AddParagraph(wxEmptyString); + PrepareContent(*this); + InvalidateHierarchy(wxRICHTEXT_ALL); } @@ -3870,7 +4075,9 @@ bool wxRichTextParagraphLayoutBox::DoNumberList(const wxRichTextRange& range, co levels[i] = -1; // start from the number we found, if any } +#if wxDEBUG_LEVEL wxASSERT(!specifyLevel || (specifyLevel && (specifiedLevel >= 0))); +#endif // If we are associated with a control, make undoable; otherwise, apply immediately // to the data. @@ -4140,7 +4347,7 @@ wxRichTextParagraph::~wxRichTextParagraph() } /// Draw the item -bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int WXUNUSED(descent), int style) +bool wxRichTextParagraph::Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int WXUNUSED(descent), int style) { if (!IsShown()) return true; @@ -4150,9 +4357,10 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& range, const wxR // for all paragraphs). But generally box attributes are likely to be // different for different objects. wxRect paraRect = GetRect(); - DrawBoxAttributes(dc, GetBuffer(), GetAttributes(), paraRect); - wxRichTextAttr attr = GetCombinedAttributes(); + context.ApplyVirtualAttributes(attr, this); + + DrawBoxAttributes(dc, GetBuffer(), attr, paraRect); // Draw the bullet, if any if (attr.GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE) @@ -4162,7 +4370,7 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& range, const wxR int spaceBeforePara = ConvertTenthsMMToPixels(dc, attr.GetParagraphSpacingBefore()); int leftIndent = ConvertTenthsMMToPixels(dc, attr.GetLeftIndent()); - wxRichTextAttr bulletAttr(GetCombinedAttributes()); + wxRichTextAttr bulletAttr(attr); // Combine with the font of the first piece of content, if one is specified if (GetChildren().GetCount() > 0) @@ -4270,13 +4478,13 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& range, const wxR #endif { int descent = 0; - child->GetRangeSize(objectRange, objectSize, descent, dc, wxRICHTEXT_UNFORMATTED, objectPosition); + child->GetRangeSize(objectRange, objectSize, descent, dc, context, wxRICHTEXT_UNFORMATTED, objectPosition); } } // Use the child object's width, but the whole line's height wxRect childRect(objectPosition, wxSize(objectSize.x, line->GetSize().y)); - child->Draw(dc, objectRange, selection, childRect, maxDescent, style); + child->Draw(dc, context, objectRange, selection, childRect, maxDescent, style); objectPosition.x += objectSize.x; i ++; @@ -4315,16 +4523,17 @@ static int wxRichTextGetRangeWidth(const wxRichTextParagraph& para, const wxRich } /// Lay the item out -bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) +bool wxRichTextParagraph::Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style) { // Deal with floating objects firstly before the normal layout wxRichTextBuffer* buffer = GetBuffer(); wxASSERT(buffer); wxRichTextFloatCollector* collector = GetContainer()->GetFloatCollector(); wxASSERT(collector); - LayoutFloat(dc, rect, style, collector); + LayoutFloat(dc, context, rect, style, collector); wxRichTextAttr attr = GetCombinedAttributes(); + context.ApplyVirtualAttributes(attr, this); // ClearLines(); @@ -4338,7 +4547,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) int lineSpacing = 0; // Let's assume line spacing of 10 is normal, 15 is 1.5, 20 is 2, etc. - if (attr.HasLineSpacing() && attr.GetLineSpacing() > 0 && attr.GetFont().Ok()) + if (attr.HasLineSpacing() && attr.GetLineSpacing() > 0 && attr.GetFont().IsOk()) { wxCheckSetFont(dc, attr.GetFont()); lineSpacing = (int) (double(dc.GetCharHeight()) * (double(attr.GetLineSpacing())/10.0 - 1.0)); @@ -4379,7 +4588,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) int paraDescent = 0; // This calculates the partial text extents - GetRangeSize(GetRange(), paraSize, paraDescent, dc, wxRICHTEXT_UNFORMATTED|wxRICHTEXT_CACHE_SIZE, rect.GetPosition(), & partialExtents); + GetRangeSize(GetRange(), paraSize, paraDescent, dc, context, wxRICHTEXT_UNFORMATTED|wxRICHTEXT_CACHE_SIZE, rect.GetPosition(), & partialExtents); #else node = m_children.GetFirst(); while (node) @@ -4387,7 +4596,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) wxRichTextObject* child = node->GetData(); //child->SetCachedSize(wxDefaultSize); - child->Layout(dc, rect, style); + child->Layout(dc, context, rect, style); node = node->GetNext(); } @@ -4454,15 +4663,15 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) // lays out the object again using the minimum size // The position will be determined by its location in its line, // and not by the child's actual position. - child->LayoutToBestSize(dc, buffer, - GetAttributes(), child->GetAttributes(), availableRect, style); + child->LayoutToBestSize(dc, context, buffer, + attr, child->GetAttributes(), availableRect, parentRect, style); if (oldSize != child->GetCachedSize()) { partialExtents.Clear(); // Recalculate the partial text extents since the child object changed size - GetRangeSize(GetRange(), paraSize, paraDescent, dc, wxRICHTEXT_UNFORMATTED|wxRICHTEXT_CACHE_SIZE, wxPoint(0,0), & partialExtents); + GetRangeSize(GetRange(), paraSize, paraDescent, dc, context, wxRICHTEXT_UNFORMATTED|wxRICHTEXT_CACHE_SIZE, wxPoint(0,0), & partialExtents); } } @@ -4479,10 +4688,10 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) { #if wxRICHTEXT_USE_PARTIAL_TEXT_EXTENTS // Get height only, then the width using the partial extents - GetRangeSize(wxRichTextRange(lastEndPos+1, lastPosToUse), childSize, childDescent, dc, wxRICHTEXT_UNFORMATTED|wxRICHTEXT_HEIGHT_ONLY); + GetRangeSize(wxRichTextRange(lastEndPos+1, lastPosToUse), childSize, childDescent, dc, context, wxRICHTEXT_UNFORMATTED|wxRICHTEXT_HEIGHT_ONLY); childSize.x = wxRichTextGetRangeWidth(*this, wxRichTextRange(lastEndPos+1, lastPosToUse), partialExtents); #else - GetRangeSize(wxRichTextRange(lastEndPos+1, lastPosToUse), childSize, childDescent, dc, wxRICHTEXT_UNFORMATTED, rect.GetPosition()); + GetRangeSize(wxRichTextRange(lastEndPos+1, lastPosToUse), childSize, childDescent, dc, context, wxRICHTEXT_UNFORMATTED, rect.GetPosition()); #endif } @@ -4538,8 +4747,8 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) // 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 child->Invalidate(wxRICHTEXT_ALL); - child->LayoutToBestSize(dc, buffer, - GetAttributes(), child->GetAttributes(), availableRect, style); + child->LayoutToBestSize(dc, context, buffer, + attr, child->GetAttributes(), availableRect, parentRect, style); childSize = child->GetCachedSize(); childDescent = child->GetDescent(); //child->SetPosition(availableRect.GetPosition()); @@ -4549,7 +4758,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) partialExtents.Clear(); // Recalculate the partial text extents since the child object changed size - GetRangeSize(GetRange(), paraSize, paraDescent, dc, wxRICHTEXT_UNFORMATTED|wxRICHTEXT_CACHE_SIZE, wxPoint(0,0), & partialExtents); + GetRangeSize(GetRange(), paraSize, paraDescent, dc, context, wxRICHTEXT_UNFORMATTED|wxRICHTEXT_CACHE_SIZE, wxPoint(0,0), & partialExtents); } // Go around the loop finding the available rect for the given floating objects @@ -4592,7 +4801,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) // Note: one object must contains only one wxTextAtrr, so the line height will not // change inside one object. Thus, we can pass the remain line width to the // FindWrapPosition function. - if (!FindWrapPosition(wxRichTextRange(lastCompletedEndPos+1, child->GetRange().GetEnd()), dc, availableRect.width, wrapPosition, & partialExtents)) + if (!FindWrapPosition(wxRichTextRange(lastCompletedEndPos+1, child->GetRange().GetEnd()), dc, context, availableRect.width, wrapPosition, & partialExtents)) { // If the function failed, just cut it off at the end of this child. wrapPosition = child->GetRange().GetEnd(); @@ -4620,12 +4829,12 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) if (!child->IsEmpty()) { // Get height only, then the width using the partial extents - GetRangeSize(actualRange, actualSize, childDescent, dc, wxRICHTEXT_UNFORMATTED|wxRICHTEXT_HEIGHT_ONLY); + GetRangeSize(actualRange, actualSize, childDescent, dc, context, wxRICHTEXT_UNFORMATTED|wxRICHTEXT_HEIGHT_ONLY); actualSize.x = wxRichTextGetRangeWidth(*this, actualRange, partialExtents); } else #endif - GetRangeSize(actualRange, actualSize, childDescent, dc, wxRICHTEXT_UNFORMATTED); + GetRangeSize(actualRange, actualSize, childDescent, dc, context, wxRICHTEXT_UNFORMATTED); currentWidth = actualSize.x; maxDescent = wxMax(childDescent, maxDescent); @@ -4713,7 +4922,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) { wxRect marginRect, borderRect, contentRect, paddingRect, outlineRect; contentRect = wxRect(wxPoint(0, 0), wxSize(maxWidth, currentPosition.y + spaceAfterPara)); - GetBoxRects(dc, buffer, GetAttributes(), marginRect, borderRect, contentRect, paddingRect, outlineRect); + GetBoxRects(dc, buffer, attr, marginRect, borderRect, contentRect, paddingRect, outlineRect); SetCachedSize(marginRect.GetSize()); } @@ -4722,8 +4931,8 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) // this size. TODO: take into account line breaks. { wxRect marginRect, borderRect, contentRect, paddingRect, outlineRect; - contentRect = wxRect(wxPoint(0, 0), wxSize(paraSize.x, currentPosition.y + spaceAfterPara)); - GetBoxRects(dc, buffer, GetAttributes(), marginRect, borderRect, contentRect, paddingRect, outlineRect); + contentRect = wxRect(wxPoint(0, 0), wxSize(paraSize.x + wxMax(leftIndent, leftIndent + leftSubIndent) + rightIndent, currentPosition.y + spaceAfterPara)); + GetBoxRects(dc, buffer, attr, marginRect, borderRect, contentRect, paddingRect, outlineRect); SetMaxSize(marginRect.GetSize()); } @@ -4750,7 +4959,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) wxRect marginRect, borderRect, contentRect, paddingRect, outlineRect; contentRect = wxRect(wxPoint(0, 0), wxSize(minWidth, currentPosition.y + spaceAfterPara)); - GetBoxRects(dc, buffer, GetAttributes(), marginRect, borderRect, contentRect, paddingRect, outlineRect); + GetBoxRects(dc, buffer, attr, marginRect, borderRect, contentRect, paddingRect, outlineRect); SetMinSize(marginRect.GetSize()); } @@ -4811,13 +5020,13 @@ void wxRichTextParagraph::ApplyParagraphStyle(wxRichTextLine* line, const wxRich wxSize size = line->GetSize(); // centering, right-justification - if (attr.HasAlignment() && GetAttributes().GetAlignment() == wxTEXT_ALIGNMENT_CENTRE) + if (attr.HasAlignment() && attr.GetAlignment() == wxTEXT_ALIGNMENT_CENTRE) { int rightIndent = ConvertTenthsMMToPixels(dc, attr.GetRightIndent()); pos.x = (rect.GetWidth() - rightIndent - size.x)/2 + pos.x; line->SetPosition(pos); } - else if (attr.HasAlignment() && GetAttributes().GetAlignment() == wxTEXT_ALIGNMENT_RIGHT) + else if (attr.HasAlignment() && attr.GetAlignment() == wxTEXT_ALIGNMENT_RIGHT) { int rightIndent = ConvertTenthsMMToPixels(dc, attr.GetRightIndent()); pos.x = pos.x + rect.GetWidth() - size.x - rightIndent; @@ -4908,7 +5117,7 @@ void wxRichTextParagraph::ClearLines() /// Get/set the object size for the given range. Returns false if the range /// is invalid for this object. -bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position, wxArrayInt* partialExtents) const +bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int flags, wxPoint position, wxArrayInt* partialExtents) const { if (!range.IsWithin(GetRange())) return false; @@ -4996,7 +5205,7 @@ bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& siz partialExtents->Add(childSize.x + lastSize); } } - else if (child->GetRangeSize(rangeToUse, childSize, childDescent, dc, flags, wxPoint(position.x + sz.x, position.y), p)) + else if (child->GetRangeSize(rangeToUse, childSize, childDescent, dc, context, flags, wxPoint(position.x + sz.x, position.y), p)) { sz.y = wxMax(sz.y, childSize.y); sz.x += childSize.x; @@ -5068,7 +5277,7 @@ bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& siz wxSize childSize; int childDescent = 0; - if (child->GetRangeSize(rangeToUse, childSize, childDescent, dc, flags, wxPoint(position.x + sz.x, position.y))) + if (child->GetRangeSize(rangeToUse, childSize, childDescent, dc, context, flags, wxPoint(position.x + sz.x, position.y))) { lineSize.y = wxMax(lineSize.y, childSize.y); lineSize.x += childSize.x; @@ -5091,7 +5300,7 @@ bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& siz } /// Finds the absolute position and row height for the given character position -bool wxRichTextParagraph::FindPosition(wxDC& dc, long index, wxPoint& pt, int* height, bool forceLineStart) +bool wxRichTextParagraph::FindPosition(wxDC& dc, wxRichTextDrawingContext& context, long index, wxPoint& pt, int* height, bool forceLineStart) { if (index == -1) { @@ -5167,7 +5376,7 @@ bool wxRichTextParagraph::FindPosition(wxDC& dc, long index, wxPoint& pt, int* h // then we can add this size to the line start position and // paragraph start position to find the actual position. - if (GetRangeSize(r, rangeSize, descent, dc, wxRICHTEXT_UNFORMATTED, line->GetPosition()+ GetPosition())) + if (GetRangeSize(r, rangeSize, descent, dc, context, wxRICHTEXT_UNFORMATTED, line->GetPosition()+ GetPosition())) { pt.x = line->GetPosition().x + GetPosition().x + rangeSize.x; *height = line->GetSize().y; @@ -5185,7 +5394,7 @@ bool wxRichTextParagraph::FindPosition(wxDC& dc, long index, wxPoint& pt, int* h /// Hit-testing: returns a flag indicating hit test details, plus /// information about position -int wxRichTextParagraph::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags) +int wxRichTextParagraph::HitTest(wxDC& dc, wxRichTextDrawingContext& context, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags) { if (!IsShown()) return wxRICHTEXT_HITTEST_NONE; @@ -5202,7 +5411,7 @@ int wxRichTextParagraph::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition { long tmpPos; wxRichTextObject* tempObj, *tempContextObj; - if (GetParent() && GetParent()->wxRichTextObject::HitTest(dc, pt, tmpPos, & tempObj, & tempContextObj, flags) == wxRICHTEXT_HITTEST_NONE) + if (GetParent() && GetParent()->wxRichTextObject::HitTest(dc, context, pt, tmpPos, & tempObj, & tempContextObj, flags) == wxRICHTEXT_HITTEST_NONE) return wxRICHTEXT_HITTEST_NONE; } @@ -5213,7 +5422,7 @@ int wxRichTextParagraph::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition if (child->IsTopLevel() && ((flags & wxRICHTEXT_HITTEST_NO_NESTED_OBJECTS) == 0)) { { - int hitTest = child->HitTest(dc, pt, textPosition, obj, contextObj); + int hitTest = child->HitTest(dc, context, pt, textPosition, obj, contextObj); if (hitTest != wxRICHTEXT_HITTEST_NONE) return hitTest; } @@ -5257,7 +5466,7 @@ int wxRichTextParagraph::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition int paraDescent; // This calculates the partial text extents - GetRangeSize(lineRange, paraSize, paraDescent, dc, wxRICHTEXT_UNFORMATTED, linePos, & partialExtents); + GetRangeSize(lineRange, paraSize, paraDescent, dc, context, wxRICHTEXT_UNFORMATTED, linePos, & partialExtents); int lastX = linePos.x; size_t i; @@ -5295,7 +5504,7 @@ int wxRichTextParagraph::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition wxRichTextRange rangeToUse(lineRange.GetStart(), i); - GetRangeSize(rangeToUse, childSize, descent, dc, wxRICHTEXT_UNFORMATTED, linePos); + GetRangeSize(rangeToUse, childSize, descent, dc, context, wxRICHTEXT_UNFORMATTED, linePos); int nextX = childSize.x + linePos.x; @@ -5497,7 +5706,7 @@ bool wxRichTextParagraph::GetContiguousPlainText(wxString& text, const wxRichTex } /// Find a suitable wrap position. -bool wxRichTextParagraph::FindWrapPosition(const wxRichTextRange& range, wxDC& dc, int availableSpace, long& wrapPosition, wxArrayInt* partialExtents) +bool wxRichTextParagraph::FindWrapPosition(const wxRichTextRange& range, wxDC& dc, wxRichTextDrawingContext& context, int availableSpace, long& wrapPosition, wxArrayInt* partialExtents) { if (range.GetLength() <= 0) return false; @@ -5539,7 +5748,7 @@ bool wxRichTextParagraph::FindWrapPosition(const wxRichTextRange& range, wxDC& d if (minPos == maxPos) { int descent = 0; - GetRangeSize(wxRichTextRange(range.GetStart(), minPos), sz, descent, dc, wxRICHTEXT_UNFORMATTED); + GetRangeSize(wxRichTextRange(range.GetStart(), minPos), sz, descent, dc, context, wxRICHTEXT_UNFORMATTED); if (sz.x > availableSpace) breakPosition = minPos - 1; @@ -5548,13 +5757,13 @@ bool wxRichTextParagraph::FindWrapPosition(const wxRichTextRange& range, wxDC& d else if ((maxPos - minPos) == 1) { int descent = 0; - GetRangeSize(wxRichTextRange(range.GetStart(), minPos), sz, descent, dc, wxRICHTEXT_UNFORMATTED); + GetRangeSize(wxRichTextRange(range.GetStart(), minPos), sz, descent, dc, context, wxRICHTEXT_UNFORMATTED); if (sz.x > availableSpace) breakPosition = minPos - 1; else { - GetRangeSize(wxRichTextRange(range.GetStart(), maxPos), sz, descent, dc, wxRICHTEXT_UNFORMATTED); + GetRangeSize(wxRichTextRange(range.GetStart(), maxPos), sz, descent, dc, context, wxRICHTEXT_UNFORMATTED); if (sz.x > availableSpace) breakPosition = maxPos-1; } @@ -5565,7 +5774,7 @@ bool wxRichTextParagraph::FindWrapPosition(const wxRichTextRange& range, wxDC& d long nextPos = minPos + ((maxPos - minPos) / 2); int descent = 0; - GetRangeSize(wxRichTextRange(range.GetStart(), nextPos), sz, descent, dc, wxRICHTEXT_UNFORMATTED); + GetRangeSize(wxRichTextRange(range.GetStart(), nextPos), sz, descent, dc, context, wxRICHTEXT_UNFORMATTED); if (sz.x > availableSpace) { @@ -5768,7 +5977,7 @@ void wxRichTextParagraph::ClearDefaultTabs() sm_defaultTabs.Clear(); } -void wxRichTextParagraph::LayoutFloat(wxDC& dc, const wxRect& rect, int style, wxRichTextFloatCollector* floatCollector) +void wxRichTextParagraph::LayoutFloat(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, int style, wxRichTextFloatCollector* floatCollector) { wxRichTextObjectList::compatibility_iterator node = GetChildren().GetFirst(); while (node) @@ -5778,7 +5987,7 @@ void wxRichTextParagraph::LayoutFloat(wxDC& dc, const wxRect& rect, int style, w { wxSize size; int descent, x = 0; - anchored->GetRangeSize(anchored->GetRange(), size, descent, dc, style); + anchored->GetRangeSize(anchored->GetRange(), size, descent, dc, context, style); int offsetY = 0; if (anchored->GetAttributes().GetTextBoxAttr().GetTop().IsValid()) @@ -5907,12 +6116,13 @@ wxRichTextPlainText::wxRichTextPlainText(const wxString& text, wxRichTextObject* #define WIDTH_FOR_DEFAULT_TABS 50 /// Draw the item -bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int WXUNUSED(style)) +bool wxRichTextPlainText::Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int WXUNUSED(style)) { wxRichTextParagraph* para = wxDynamicCast(GetParent(), wxRichTextParagraph); wxASSERT (para != NULL); wxRichTextAttr textAttr(para ? para->GetCombinedAttributes(GetAttributes(), false /* no box attributes */) : GetAttributes()); + context.ApplyVirtualAttributes(textAttr, this); // Let's make the assumption for now that for content in a paragraph, including // text, we never have a discontinuous selection. So we only deal with a @@ -5949,7 +6159,7 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR int charHeight = dc.GetCharHeight(); int x, y; - if ( textFont.Ok() ) + if ( textFont.IsOk() ) { if ( textAttr.HasTextEffects() && (textAttr.GetTextEffects() & wxTEXT_ATTR_EFFECT_SUPERSCRIPT) ) { @@ -6209,11 +6419,11 @@ bool wxRichTextPlainText::DrawTabbedString(wxDC& dc, const wxRichTextAttr& attr, } /// Lay the item out -bool wxRichTextPlainText::Layout(wxDC& dc, const wxRect& WXUNUSED(rect), int WXUNUSED(style)) +bool wxRichTextPlainText::Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& WXUNUSED(rect), const wxRect& WXUNUSED(parentRect), int WXUNUSED(style)) { // Only lay out if we haven't already cached the size if (m_size.x == -1) - GetRangeSize(GetRange(), m_size, m_descent, dc, 0, wxPoint(0, 0)); + GetRangeSize(GetRange(), m_size, m_descent, dc, context, 0, wxPoint(0, 0)); m_maxSize = m_size; // Eventually we want to have a reasonable estimate of minimum size. m_minSize = wxSize(0, 0); @@ -6230,7 +6440,7 @@ void wxRichTextPlainText::Copy(const wxRichTextPlainText& obj) /// Get/set the object size for the given range. Returns false if the range /// is invalid for this object. -bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int WXUNUSED(flags), wxPoint position, wxArrayInt* partialExtents) const +bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int WXUNUSED(flags), wxPoint position, wxArrayInt* partialExtents) const { if (!range.IsWithin(GetRange())) return false; @@ -6241,6 +6451,7 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz int relativeX = position.x - GetParent()->GetPosition().x; wxRichTextAttr textAttr(para ? para->GetCombinedAttributes(GetAttributes()) : GetAttributes()); + context.ApplyVirtualAttributes(textAttr, (wxRichTextObject*) this); // Always assume unformatted text, since at this level we have no knowledge // of line breaks - and we don't need it, since we'll calculate size within @@ -6248,7 +6459,7 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz bool bScript(false); wxFont font(GetBuffer()->GetFontTable().FindFont(textAttr)); - if (font.Ok()) + if (font.IsOk()) { if ( textAttr.HasTextEffects() && ( (textAttr.GetTextEffects() & wxTEXT_ATTR_EFFECT_SUPERSCRIPT) || (textAttr.GetTextEffects() & wxTEXT_ATTR_EFFECT_SUBSCRIPT) ) ) @@ -6427,6 +6638,7 @@ wxRichTextObject* wxRichTextPlainText::DoSplit(long pos) wxRichTextPlainText* newObject = new wxRichTextPlainText(secondPart); newObject->SetAttributes(GetAttributes()); + newObject->SetProperties(GetProperties()); newObject->SetRange(wxRichTextRange(pos, GetRange().GetEnd())); GetRange().SetEnd(pos-1); @@ -6478,7 +6690,7 @@ wxString wxRichTextPlainText::GetTextForRange(const wxRichTextRange& range) cons bool wxRichTextPlainText::CanMerge(wxRichTextObject* object) const { return object->GetClassInfo() == CLASSINFO(wxRichTextPlainText) && - (m_text.empty() || wxTextAttrEq(GetAttributes(), object->GetAttributes())); + (m_text.empty() || (wxTextAttrEq(GetAttributes(), object->GetAttributes()) && m_properties == object->GetProperties())); } /// Returns true if this object merged itself with the given one. @@ -6530,6 +6742,7 @@ long wxRichTextPlainText::GetFirstLineBreakPosition(long pos) IMPLEMENT_DYNAMIC_CLASS(wxRichTextBuffer, wxRichTextParagraphLayoutBox) wxList wxRichTextBuffer::sm_handlers; +wxList wxRichTextBuffer::sm_drawingHandlers; wxRichTextRenderer* wxRichTextBuffer::sm_renderer = NULL; int wxRichTextBuffer::sm_bulletRightMargin = 20; float wxRichTextBuffer::sm_bulletProportion = (float) 0.3; @@ -6610,11 +6823,11 @@ wxRichTextStyleSheet* wxRichTextBuffer::PopStyleSheet() /// Submit command to insert paragraphs bool wxRichTextBuffer::InsertParagraphsWithUndo(long pos, const wxRichTextParagraphLayoutBox& paragraphs, wxRichTextCtrl* ctrl, int flags) { - return ctrl->GetFocusObject()->InsertParagraphsWithUndo(pos, paragraphs, ctrl, this, flags); + return ctrl->GetFocusObject()->InsertParagraphsWithUndo(this, pos, paragraphs, ctrl, flags); } /// Submit command to insert paragraphs -bool wxRichTextParagraphLayoutBox::InsertParagraphsWithUndo(long pos, const wxRichTextParagraphLayoutBox& paragraphs, wxRichTextCtrl* ctrl, wxRichTextBuffer* buffer, int WXUNUSED(flags)) +bool wxRichTextParagraphLayoutBox::InsertParagraphsWithUndo(wxRichTextBuffer* buffer, long pos, const wxRichTextParagraphLayoutBox& paragraphs, wxRichTextCtrl* ctrl, int WXUNUSED(flags)) { wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Text"), wxRICHTEXT_INSERT, buffer, this, ctrl, false); @@ -6637,11 +6850,11 @@ bool wxRichTextParagraphLayoutBox::InsertParagraphsWithUndo(long pos, const wxRi /// Submit command to insert the given text bool wxRichTextBuffer::InsertTextWithUndo(long pos, const wxString& text, wxRichTextCtrl* ctrl, int flags) { - return ctrl->GetFocusObject()->InsertTextWithUndo(pos, text, ctrl, this, flags); + return ctrl->GetFocusObject()->InsertTextWithUndo(this, pos, text, ctrl, flags); } /// Submit command to insert the given text -bool wxRichTextParagraphLayoutBox::InsertTextWithUndo(long pos, const wxString& text, wxRichTextCtrl* ctrl, wxRichTextBuffer* buffer, int flags) +bool wxRichTextParagraphLayoutBox::InsertTextWithUndo(wxRichTextBuffer* buffer, long pos, const wxString& text, wxRichTextCtrl* ctrl, int flags) { wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Text"), wxRICHTEXT_INSERT, buffer, this, ctrl, false); @@ -6681,11 +6894,11 @@ bool wxRichTextParagraphLayoutBox::InsertTextWithUndo(long pos, const wxString& /// Submit command to insert the given text bool wxRichTextBuffer::InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl, int flags) { - return ctrl->GetFocusObject()->InsertNewlineWithUndo(pos, ctrl, this, flags); + return ctrl->GetFocusObject()->InsertNewlineWithUndo(this, pos, ctrl, flags); } /// Submit command to insert the given text -bool wxRichTextParagraphLayoutBox::InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl, wxRichTextBuffer* buffer, int flags) +bool wxRichTextParagraphLayoutBox::InsertNewlineWithUndo(wxRichTextBuffer* buffer, long pos, wxRichTextCtrl* ctrl, int flags) { wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Text"), wxRICHTEXT_INSERT, buffer, this, ctrl, false); @@ -6761,12 +6974,12 @@ bool wxRichTextParagraphLayoutBox::InsertNewlineWithUndo(long pos, wxRichTextCtr bool wxRichTextBuffer::InsertImageWithUndo(long pos, const wxRichTextImageBlock& imageBlock, wxRichTextCtrl* ctrl, int flags, const wxRichTextAttr& textAttr) { - return ctrl->GetFocusObject()->InsertImageWithUndo(pos, imageBlock, ctrl, this, flags, textAttr); + return ctrl->GetFocusObject()->InsertImageWithUndo(this, pos, imageBlock, ctrl, flags, textAttr); } /// Submit command to insert the given image -bool wxRichTextParagraphLayoutBox::InsertImageWithUndo(long pos, const wxRichTextImageBlock& imageBlock, - wxRichTextCtrl* ctrl, wxRichTextBuffer* buffer, int flags, +bool wxRichTextParagraphLayoutBox::InsertImageWithUndo(wxRichTextBuffer* buffer, long pos, const wxRichTextImageBlock& imageBlock, + wxRichTextCtrl* ctrl, int flags, const wxRichTextAttr& textAttr) { wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Image"), wxRICHTEXT_INSERT, buffer, this, ctrl, false); @@ -6807,11 +7020,11 @@ bool wxRichTextParagraphLayoutBox::InsertImageWithUndo(long pos, const wxRichTex // Insert an object with no change of it wxRichTextObject* wxRichTextBuffer::InsertObjectWithUndo(long pos, wxRichTextObject *object, wxRichTextCtrl* ctrl, int flags) { - return ctrl->GetFocusObject()->InsertObjectWithUndo(pos, object, ctrl, this, flags); + return ctrl->GetFocusObject()->InsertObjectWithUndo(this, pos, object, ctrl, flags); } // Insert an object with no change of it -wxRichTextObject* wxRichTextParagraphLayoutBox::InsertObjectWithUndo(long pos, wxRichTextObject *object, wxRichTextCtrl* ctrl, wxRichTextBuffer* buffer, int flags) +wxRichTextObject* wxRichTextParagraphLayoutBox::InsertObjectWithUndo(wxRichTextBuffer* buffer, long pos, wxRichTextObject *object, wxRichTextCtrl* ctrl, int flags) { wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Object"), wxRICHTEXT_INSERT, buffer, this, ctrl, false); @@ -6998,6 +7211,9 @@ bool wxRichTextBuffer::EndBatchUndo() /// Submit immediately, or delay according to whether collapsing is on bool wxRichTextBuffer::SubmitAction(wxRichTextAction* action) { + if (action && !action->GetNewParagraphs().IsEmpty()) + PrepareContent(action->GetNewParagraphs()); + if (BatchingUndo() && m_batchedCommand && !SuppressingUndo()) { wxRichTextCommand* cmd = new wxRichTextCommand(action->GetName()); @@ -7579,7 +7795,7 @@ bool wxRichTextBuffer::PasteFromClipboard(long position) wxRichTextBuffer* richTextBuffer = data.GetRichTextBuffer(); if (richTextBuffer) { - container->InsertParagraphsWithUndo(position+1, *richTextBuffer, GetRichTextCtrl(), this, 0); + container->InsertParagraphsWithUndo(this, position+1, *richTextBuffer, GetRichTextCtrl(), 0); if (GetRichTextCtrl()) GetRichTextCtrl()->ShowPosition(position + richTextBuffer->GetOwnRange().GetEnd()); delete richTextBuffer; @@ -7607,7 +7823,7 @@ bool wxRichTextBuffer::PasteFromClipboard(long position) #else wxString text2 = text; #endif - container->InsertTextWithUndo(position+1, text2, GetRichTextCtrl(), this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE); + container->InsertTextWithUndo(this, position+1, text2, GetRichTextCtrl(), wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE); if (GetRichTextCtrl()) GetRichTextCtrl()->ShowPosition(position + text2.Length()); @@ -7774,9 +7990,9 @@ void wxRichTextBuffer::SetRenderer(wxRichTextRenderer* renderer) /// Hit-testing: returns a flag indicating hit test details, plus /// information about position -int wxRichTextBuffer::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags) +int wxRichTextBuffer::HitTest(wxDC& dc, wxRichTextDrawingContext& context, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags) { - int ret = wxRichTextParagraphLayoutBox::HitTest(dc, pt, textPosition, obj, contextObj, flags); + int ret = wxRichTextParagraphLayoutBox::HitTest(dc, context, pt, textPosition, obj, contextObj, flags); if (ret != wxRICHTEXT_HITTEST_NONE) { return ret; @@ -7792,7 +8008,7 @@ int wxRichTextBuffer::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition, w bool wxRichTextStdRenderer::DrawStandardBullet(wxRichTextParagraph* paragraph, wxDC& dc, const wxRichTextAttr& bulletAttr, const wxRect& rect) { - if (bulletAttr.GetTextColour().Ok()) + if (bulletAttr.GetTextColour().IsOk()) { wxCheckSetPen(dc, wxPen(bulletAttr.GetTextColour())); wxCheckSetBrush(dc, wxBrush(bulletAttr.GetTextColour())); @@ -7892,7 +8108,7 @@ bool wxRichTextStdRenderer::DrawTextBullet(wxRichTextParagraph* paragraph, wxDC& wxCheckSetFont(dc, font); - if (attr.GetTextColour().Ok()) + if (attr.GetTextColour().IsOk()) dc.SetTextForeground(attr.GetTextColour()); dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT); @@ -7953,7 +8169,7 @@ wxRichTextBox::wxRichTextBox(wxRichTextObject* parent): } /// Draw the item -bool wxRichTextBox::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style) +bool wxRichTextBox::Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style) { if (!IsShown()) return true; @@ -7963,7 +8179,7 @@ bool wxRichTextBox::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTex // so we can apply commands (properties, delete, ...) to objects such as text boxes and images. // Ultimately we would like to be able to interactively resize an active object // using drag handles. - return wxRichTextParagraphLayoutBox::Draw(dc, range, selection, rect, descent, style); + return wxRichTextParagraphLayoutBox::Draw(dc, context, range, selection, rect, descent, style); } /// Copy @@ -7997,9 +8213,9 @@ wxRichTextCell::wxRichTextCell(wxRichTextObject* parent): } /// Draw the item -bool wxRichTextCell::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style) +bool wxRichTextCell::Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style) { - return wxRichTextBox::Draw(dc, range, selection, rect, descent, style); + return wxRichTextBox::Draw(dc, context, range, selection, rect, descent, style); } /// Copy @@ -8093,9 +8309,9 @@ wxRichTextTable::wxRichTextTable(wxRichTextObject* parent): wxRichTextBox(parent } // Draws the object. -bool wxRichTextTable::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style) +bool wxRichTextTable::Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style) { - return wxRichTextBox::Draw(dc, range, selection, rect, descent, style); + return wxRichTextBox::Draw(dc, context, range, selection, rect, descent, style); } WX_DECLARE_OBJARRAY(wxRect, wxRichTextRectArray); @@ -8106,7 +8322,7 @@ WX_DEFINE_OBJARRAY(wxRichTextRectArray); // layout to a particular size, or it could be the total space available in the // parent. rect is the overall size, so we must subtract margins and padding. // to get the actual available space. -bool wxRichTextTable::Layout(wxDC& dc, const wxRect& rect, int style) +bool wxRichTextTable::Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& WXUNUSED(parentRect), int style) { SetPosition(rect.GetPosition()); @@ -8118,17 +8334,20 @@ bool wxRichTextTable::Layout(wxDC& dc, const wxRect& rect, int style) wxRichTextBuffer* buffer = GetBuffer(); if (buffer) scale = buffer->GetScale(); - wxRect availableSpace = GetAvailableContentArea(dc, rect); + wxRect availableSpace = GetAvailableContentArea(dc, context, rect); wxTextAttrDimensionConverter converter(dc, scale, availableSpace.GetSize()); + wxRichTextAttr attr(GetAttributes()); + context.ApplyVirtualAttributes(attr, this); + // If we have no fixed table size, and assuming we're not pushed for // space, then we don't have to try to stretch the table to fit the contents. bool stretchToFitTableWidth = false; int tableWidth = rect.width; - if (GetAttributes().GetTextBoxAttr().GetWidth().IsValid()) + if (attr.GetTextBoxAttr().GetWidth().IsValid()) { - tableWidth = converter.GetPixels(GetAttributes().GetTextBoxAttr().GetWidth()); + tableWidth = converter.GetPixels(attr.GetTextBoxAttr().GetWidth()); // Fixed table width, so we do want to stretch columns out if necessary. stretchToFitTableWidth = true; @@ -8138,22 +8357,18 @@ bool wxRichTextTable::Layout(wxDC& dc, const wxRect& rect, int style) } // Get internal padding - int paddingLeft = 0, paddingRight = 0, paddingTop = 0, paddingBottom = 0; - if (GetAttributes().GetTextBoxAttr().GetPadding().GetLeft().IsValid()) - paddingLeft = converter.GetPixels(GetAttributes().GetTextBoxAttr().GetPadding().GetLeft()); - if (GetAttributes().GetTextBoxAttr().GetPadding().GetRight().IsValid()) - paddingRight = converter.GetPixels(GetAttributes().GetTextBoxAttr().GetPadding().GetRight()); - if (GetAttributes().GetTextBoxAttr().GetPadding().GetTop().IsValid()) - paddingTop = converter.GetPixels(GetAttributes().GetTextBoxAttr().GetPadding().GetTop()); - if (GetAttributes().GetTextBoxAttr().GetPadding().GetLeft().IsValid()) - paddingBottom = converter.GetPixels(GetAttributes().GetTextBoxAttr().GetPadding().GetBottom()); + int paddingLeft = 0, paddingTop = 0; + if (attr.GetTextBoxAttr().GetPadding().GetLeft().IsValid()) + paddingLeft = converter.GetPixels(attr.GetTextBoxAttr().GetPadding().GetLeft()); + if (attr.GetTextBoxAttr().GetPadding().GetTop().IsValid()) + paddingTop = converter.GetPixels(attr.GetTextBoxAttr().GetPadding().GetTop()); // Assume that left and top padding are also used for inter-cell padding. int paddingX = paddingLeft; int paddingY = paddingTop; int totalLeftMargin = 0, totalRightMargin = 0, totalTopMargin = 0, totalBottomMargin = 0; - GetTotalMargin(dc, buffer, GetAttributes(), totalLeftMargin, totalRightMargin, totalTopMargin, totalBottomMargin); + GetTotalMargin(dc, buffer, attr, totalLeftMargin, totalRightMargin, totalTopMargin, totalBottomMargin); // Internal table width - the area for content int internalTableWidth = tableWidth - totalLeftMargin - totalRightMargin; @@ -8171,16 +8386,21 @@ bool wxRichTextTable::Layout(wxDC& dc, const wxRect& rect, int style) } // The final calculated widths - wxArrayInt colWidths(m_colCount); + wxArrayInt colWidths; + colWidths.Add(0, m_colCount); - wxArrayInt absoluteColWidths(m_colCount); + wxArrayInt absoluteColWidths; + absoluteColWidths.Add(0, m_colCount); // wxArrayInt absoluteColWidthsSpanning(m_colCount); - wxArrayInt percentageColWidths(m_colCount); + wxArrayInt percentageColWidths; + percentageColWidths.Add(0, m_colCount); // wxArrayInt percentageColWidthsSpanning(m_colCount); // These are only relevant when the first column contains spanning information. // wxArrayInt columnSpans(m_colCount); // Each contains 1 for non-spanning cell, > 1 for spanning cell. - wxArrayInt maxColWidths(m_colCount); - wxArrayInt minColWidths(m_colCount); + wxArrayInt maxColWidths; + maxColWidths.Add(0, m_colCount); + wxArrayInt minColWidths; + minColWidths.Add(0, m_colCount); wxSize tableSize(tableWidth, 0); @@ -8322,7 +8542,7 @@ bool wxRichTextTable::Layout(wxDC& dc, const wxRect& rect, int style) // Lay out cell to find min/max widths cell->Invalidate(wxRICHTEXT_ALL); - cell->Layout(dc, availableSpace, style); + cell->Layout(dc, context, availableSpace, availableSpace, style); if (colSpan == 1) { @@ -8613,7 +8833,8 @@ bool wxRichTextTable::Layout(wxDC& dc, const wxRect& rect, int style) int maxCellHeight = 0; int maxSpecifiedCellHeight = 0; - wxArrayInt actualWidths(m_colCount); + wxArrayInt actualWidths; + actualWidths.Add(0, m_colCount); wxTextAttrDimensionConverter converter(dc, scale); for (i = 0; i < m_colCount; i++) @@ -8660,7 +8881,7 @@ bool wxRichTextTable::Layout(wxDC& dc, const wxRect& rect, int style) // Lay out cell cell->Invalidate(wxRICHTEXT_ALL); - cell->Layout(dc, availableCellSpace, style); + cell->Layout(dc, context, availableCellSpace, availableSpace, style); // TODO: use GetCachedSize().x to compute 'natural' size @@ -8681,7 +8902,7 @@ bool wxRichTextTable::Layout(wxDC& dc, const wxRect& rect, int style) wxRect availableCellSpace = wxRect(cell->GetPosition(), wxSize(actualWidths[i], maxCellHeight)); // Lay out cell with new height cell->Invalidate(wxRICHTEXT_ALL); - cell->Layout(dc, availableCellSpace, style); + cell->Layout(dc, context, availableCellSpace, availableSpace, style); // Make sure the cell size really is the appropriate size, // not the calculated box size @@ -8700,7 +8921,7 @@ bool wxRichTextTable::Layout(wxDC& dc, const wxRect& rect, int style) { wxRect marginRect, borderRect, contentRect, paddingRect, outlineRect; contentRect = wxRect(wxPoint(0, 0), wxSize(maxRight - availableSpace.x, y - availableSpace.y)); - GetBoxRects(dc, GetBuffer(), GetAttributes(), marginRect, borderRect, contentRect, paddingRect, outlineRect); + GetBoxRects(dc, GetBuffer(), attr, marginRect, borderRect, contentRect, paddingRect, outlineRect); SetCachedSize(marginRect.GetSize()); } @@ -8730,14 +8951,14 @@ bool wxRichTextTable::Layout(wxDC& dc, const wxRect& rect, int style) } // Finds the absolute position and row height for the given character position -bool wxRichTextTable::FindPosition(wxDC& dc, long index, wxPoint& pt, int* height, bool forceLineStart) +bool wxRichTextTable::FindPosition(wxDC& dc, wxRichTextDrawingContext& context, long index, wxPoint& pt, int* height, bool forceLineStart) { wxRichTextCell* child = GetCell(index+1); if (child) { // Find the position at the start of the child cell, since the table doesn't // have any caret position of its own. - return child->FindPosition(dc, -1, pt, height, forceLineStart); + return child->FindPosition(dc, context, -1, pt, height, forceLineStart); } else return false; @@ -8815,9 +9036,9 @@ void wxRichTextTable::CalculateRange(long start, long& end) } // Gets the range size. -bool wxRichTextTable::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position, wxArrayInt* partialExtents) const +bool wxRichTextTable::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int flags, wxPoint position, wxArrayInt* partialExtents) const { - return wxRichTextBox::GetRangeSize(range, size, descent, dc, flags, position, partialExtents); + return wxRichTextBox::GetRangeSize(range, size, descent, dc, context, flags, position, partialExtents); } // Deletes content in the given range. @@ -9169,6 +9390,7 @@ public: void OnExit() { wxRichTextBuffer::CleanUpHandlers(); + wxRichTextBuffer::CleanUpDrawingHandlers(); wxRichTextDecimalToRoman(-1); wxRichTextParagraph::ClearDefaultTabs(); wxRichTextCtrl::ClearAvailableFontNames(); @@ -9432,6 +9654,7 @@ bool wxRichTextAction::Do() break; } case wxRICHTEXT_CHANGE_STYLE: + case wxRICHTEXT_CHANGE_PROPERTIES: { ApplyParagraphs(GetNewParagraphs()); @@ -9442,7 +9665,7 @@ bool wxRichTextAction::Do() UpdateAppearance(GetPosition()); wxRichTextEvent cmdEvent( - wxEVT_COMMAND_RICHTEXT_STYLE_CHANGED, + m_cmdId == wxRICHTEXT_CHANGE_STYLE ? wxEVT_COMMAND_RICHTEXT_STYLE_CHANGED : wxEVT_COMMAND_RICHTEXT_PROPERTIES_CHANGED, m_ctrl ? m_ctrl->GetId() : -1); cmdEvent.SetEventObject(m_ctrl ? (wxObject*) m_ctrl : (wxObject*) m_buffer); cmdEvent.SetRange(GetRange()); @@ -9585,6 +9808,7 @@ bool wxRichTextAction::Undo() break; } case wxRICHTEXT_CHANGE_STYLE: + case wxRICHTEXT_CHANGE_PROPERTIES: { ApplyParagraphs(GetOldParagraphs()); // InvalidateHierarchy goes up the hierarchy as well as down, otherwise with a nested object, @@ -9594,7 +9818,7 @@ bool wxRichTextAction::Undo() UpdateAppearance(GetPosition()); wxRichTextEvent cmdEvent( - wxEVT_COMMAND_RICHTEXT_STYLE_CHANGED, + m_cmdId == wxRICHTEXT_CHANGE_STYLE ? wxEVT_COMMAND_RICHTEXT_STYLE_CHANGED : wxEVT_COMMAND_RICHTEXT_PROPERTIES_CHANGED, m_ctrl ? m_ctrl->GetId() : -1); cmdEvent.SetEventObject(m_ctrl ? (wxObject*) m_ctrl : (wxObject*) m_buffer); cmdEvent.SetRange(GetRange()); @@ -9901,7 +10125,7 @@ bool wxRichTextImage::LoadImageCache(wxDC& dc, bool resetCache) } /// Draw the item -bool wxRichTextImage::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int WXUNUSED(descent), int WXUNUSED(style)) +bool wxRichTextImage::Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int WXUNUSED(descent), int WXUNUSED(style)) { if (!IsShown()) return true; @@ -9911,7 +10135,10 @@ bool wxRichTextImage::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichT if (!LoadImageCache(dc)) return false; - DrawBoxAttributes(dc, GetBuffer(), GetAttributes(), wxRect(GetPosition(), GetCachedSize())); + wxRichTextAttr attr(GetAttributes()); + context.ApplyVirtualAttributes(attr, this); + + DrawBoxAttributes(dc, GetBuffer(), attr, wxRect(rect.GetPosition(), GetCachedSize())); #if 0 int y = rect.y + (rect.height - m_imageCache.GetHeight()); @@ -9922,7 +10149,7 @@ bool wxRichTextImage::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichT wxSize imageSize(m_imageCache.GetWidth(), m_imageCache.GetHeight()); wxRect marginRect, borderRect, contentRect, paddingRect, outlineRect; marginRect = rect; // outer rectangle, will calculate contentRect - GetBoxRects(dc, GetBuffer(), GetAttributes(), marginRect, borderRect, contentRect, paddingRect, outlineRect); + GetBoxRects(dc, GetBuffer(), attr, marginRect, borderRect, contentRect, paddingRect, outlineRect); dc.DrawBitmap(m_imageCache, contentRect.x, contentRect.y, true); @@ -9939,7 +10166,7 @@ bool wxRichTextImage::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichT } /// Lay the item out -bool wxRichTextImage::Layout(wxDC& dc, const wxRect& rect, int WXUNUSED(style)) +bool wxRichTextImage::Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& WXUNUSED(parentRect), int WXUNUSED(style)) { if (!LoadImageCache(dc)) return false; @@ -9947,7 +10174,11 @@ bool wxRichTextImage::Layout(wxDC& dc, const wxRect& rect, int WXUNUSED(style)) wxSize imageSize(m_imageCache.GetWidth(), m_imageCache.GetHeight()); wxRect marginRect, borderRect, contentRect, paddingRect, outlineRect; contentRect = wxRect(wxPoint(0,0), imageSize); - GetBoxRects(dc, GetBuffer(), GetAttributes(), marginRect, borderRect, contentRect, paddingRect, outlineRect); + + wxRichTextAttr attr(GetAttributes()); + context.ApplyVirtualAttributes(attr, this); + + GetBoxRects(dc, GetBuffer(), attr, marginRect, borderRect, contentRect, paddingRect, outlineRect); wxSize overallSize = marginRect.GetSize(); @@ -9961,7 +10192,7 @@ bool wxRichTextImage::Layout(wxDC& dc, const wxRect& rect, int WXUNUSED(style)) /// Get/set the object size for the given range. Returns false if the range /// is invalid for this object. -bool wxRichTextImage::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& WXUNUSED(descent), wxDC& dc, int WXUNUSED(flags), wxPoint WXUNUSED(position), wxArrayInt* partialExtents) const +bool wxRichTextImage::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& WXUNUSED(descent), wxDC& dc, wxRichTextDrawingContext& context, int WXUNUSED(flags), wxPoint WXUNUSED(position), wxArrayInt* partialExtents) const { if (!range.IsWithin(GetRange())) return false; @@ -9974,10 +10205,13 @@ bool wxRichTextImage::GetRangeSize(const wxRichTextRange& range, wxSize& size, i return false; } + wxRichTextAttr attr(GetAttributes()); + context.ApplyVirtualAttributes(attr, (wxRichTextObject*) this); + wxSize imageSize(m_imageCache.GetWidth(), m_imageCache.GetHeight()); wxRect marginRect, borderRect, contentRect, paddingRect, outlineRect; contentRect = wxRect(wxPoint(0,0), imageSize); - GetBoxRects(dc, GetBuffer(), GetAttributes(), marginRect, borderRect, contentRect, paddingRect, outlineRect); + GetBoxRects(dc, GetBuffer(), attr, marginRect, borderRect, contentRect, paddingRect, outlineRect); wxSize overallSize = marginRect.GetSize(); @@ -10153,7 +10387,7 @@ IMPLEMENT_CLASS(wxRichTextFileHandler, wxObject) bool wxRichTextFileHandler::LoadFile(wxRichTextBuffer *buffer, const wxString& filename) { wxFFileInputStream stream(filename); - if (stream.Ok()) + if (stream.IsOk()) return LoadFile(buffer, stream); return false; @@ -10162,7 +10396,7 @@ bool wxRichTextFileHandler::LoadFile(wxRichTextBuffer *buffer, const wxString& f bool wxRichTextFileHandler::SaveFile(wxRichTextBuffer *buffer, const wxString& filename) { wxFFileOutputStream stream(filename); - if (stream.Ok()) + if (stream.IsOk()) return SaveFile(buffer, stream); return false; @@ -10421,8 +10655,8 @@ bool wxRichTextImageBlock::WriteHex(wxOutputStream& stream) return true; int bufSize = 100000; - if (int(m_dataSize+1) < bufSize) - bufSize = m_dataSize+1; + if (int(2*m_dataSize) < bufSize) + bufSize = 2*m_dataSize; char* buf = new char[bufSize+1]; int left = m_dataSize; @@ -10496,7 +10730,7 @@ unsigned char* wxRichTextImageBlock::ReadBlock(wxInputStream& stream, size_t siz unsigned char* wxRichTextImageBlock::ReadBlock(const wxString& filename, size_t size) { wxFileInputStream stream(filename); - if (!stream.Ok()) + if (!stream.IsOk()) return NULL; return ReadBlock(stream, size); @@ -10514,7 +10748,7 @@ bool wxRichTextImageBlock::WriteBlock(wxOutputStream& stream, unsigned char* blo bool wxRichTextImageBlock::WriteBlock(const wxString& filename, unsigned char* block, size_t size) { wxFileOutputStream outStream(filename); - if (!outStream.Ok()) + if (!outStream.IsOk()) return false; return WriteBlock(outStream, block, size); @@ -10736,12 +10970,15 @@ void wxTextBoxAttr::Reset() m_clearMode = wxTEXT_BOX_ATTR_CLEAR_NONE; m_collapseMode = wxTEXT_BOX_ATTR_COLLAPSE_NONE; m_verticalAlignment = wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_NONE; + m_boxStyleName = wxEmptyString; m_margins.Reset(); m_padding.Reset(); m_position.Reset(); m_size.Reset(); + m_minSize.Reset(); + m_maxSize.Reset(); m_border.Reset(); m_outline.Reset(); @@ -10762,9 +10999,13 @@ bool wxTextBoxAttr::operator== (const wxTextBoxAttr& attr) const m_position == attr.m_position && m_size == attr.m_size && + m_minSize == attr.m_minSize && + m_maxSize == attr.m_maxSize && m_border == attr.m_border && - m_outline == attr.m_outline + m_outline == attr.m_outline && + + m_boxStyleName == attr.m_boxStyleName ); } @@ -10783,11 +11024,23 @@ bool wxTextBoxAttr::EqPartial(const wxTextBoxAttr& attr) const if (attr.HasVerticalAlignment() && HasVerticalAlignment() && (attr.GetVerticalAlignment() != GetVerticalAlignment())) return false; + if (attr.HasBoxStyleName() && HasBoxStyleName() && (attr.GetBoxStyleName() != GetBoxStyleName())) + return false; + // Position if (!m_position.EqPartial(attr.m_position)) return false; + // Size + + if (!m_size.EqPartial(attr.m_size)) + return false; + if (!m_minSize.EqPartial(attr.m_minSize)) + return false; + if (!m_maxSize.EqPartial(attr.m_maxSize)) + return false; + // Margins if (!m_margins.EqPartial(attr.m_margins)) @@ -10840,11 +11093,19 @@ bool wxTextBoxAttr::Apply(const wxTextBoxAttr& attr, const wxTextBoxAttr* compar SetVerticalAlignment(attr.GetVerticalAlignment()); } + if (attr.HasBoxStyleName()) + { + if (!(compareWith && compareWith->HasBoxStyleName() && compareWith->GetBoxStyleName() == attr.GetBoxStyleName())) + SetBoxStyleName(attr.GetBoxStyleName()); + } + m_margins.Apply(attr.m_margins, compareWith ? (& attr.m_margins) : (const wxTextAttrDimensions*) NULL); m_padding.Apply(attr.m_padding, compareWith ? (& attr.m_padding) : (const wxTextAttrDimensions*) NULL); m_position.Apply(attr.m_position, compareWith ? (& attr.m_position) : (const wxTextAttrDimensions*) NULL); m_size.Apply(attr.m_size, compareWith ? (& attr.m_size) : (const wxTextAttrSize*) NULL); + m_minSize.Apply(attr.m_minSize, compareWith ? (& attr.m_minSize) : (const wxTextAttrSize*) NULL); + m_maxSize.Apply(attr.m_maxSize, compareWith ? (& attr.m_maxSize) : (const wxTextAttrSize*) NULL); m_border.Apply(attr.m_border, compareWith ? (& attr.m_border) : (const wxTextAttrBorders*) NULL); m_outline.Apply(attr.m_outline, compareWith ? (& attr.m_outline) : (const wxTextAttrBorders*) NULL); @@ -10867,11 +11128,19 @@ bool wxTextBoxAttr::RemoveStyle(const wxTextBoxAttr& attr) if (attr.HasVerticalAlignment()) RemoveFlag(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT); + if (attr.HasBoxStyleName()) + { + SetBoxStyleName(wxEmptyString); + RemoveFlag(wxTEXT_BOX_ATTR_BOX_STYLE_NAME); + } + m_margins.RemoveStyle(attr.m_margins); m_padding.RemoveStyle(attr.m_padding); m_position.RemoveStyle(attr.m_position); m_size.RemoveStyle(attr.m_size); + m_minSize.RemoveStyle(attr.m_minSize); + m_maxSize.RemoveStyle(attr.m_maxSize); m_border.RemoveStyle(attr.m_border); m_outline.RemoveStyle(attr.m_outline); @@ -10959,16 +11228,44 @@ void wxTextBoxAttr::CollectCommonAttributes(const wxTextBoxAttr& attr, wxTextBox else absentAttr.AddFlag(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT); + if (attr.HasBoxStyleName()) + { + if (!clashingAttr.HasBoxStyleName() && !absentAttr.HasBoxStyleName()) + { + if (HasBoxStyleName()) + { + if (GetBoxStyleName() != attr.GetBoxStyleName()) + { + clashingAttr.AddFlag(wxTEXT_BOX_ATTR_BOX_STYLE_NAME); + RemoveFlag(wxTEXT_BOX_ATTR_BOX_STYLE_NAME); + } + } + else + SetBoxStyleName(attr.GetBoxStyleName()); + } + } + else + absentAttr.AddFlag(wxTEXT_BOX_ATTR_BOX_STYLE_NAME); + m_margins.CollectCommonAttributes(attr.m_margins, clashingAttr.m_margins, absentAttr.m_margins); m_padding.CollectCommonAttributes(attr.m_padding, clashingAttr.m_padding, absentAttr.m_padding); m_position.CollectCommonAttributes(attr.m_position, clashingAttr.m_position, absentAttr.m_position); m_size.CollectCommonAttributes(attr.m_size, clashingAttr.m_size, absentAttr.m_size); + m_minSize.CollectCommonAttributes(attr.m_minSize, clashingAttr.m_minSize, absentAttr.m_minSize); + m_maxSize.CollectCommonAttributes(attr.m_maxSize, clashingAttr.m_maxSize, absentAttr.m_maxSize); m_border.CollectCommonAttributes(attr.m_border, clashingAttr.m_border, absentAttr.m_border); m_outline.CollectCommonAttributes(attr.m_outline, clashingAttr.m_outline, absentAttr.m_outline); } +bool wxTextBoxAttr::IsDefault() const +{ + return GetFlags() == 0 && !m_border.IsValid() && !m_outline.IsValid() && + !m_size.IsValid() && !m_minSize.IsValid() && !m_maxSize.IsValid() && + !m_position.IsValid() && !m_padding.IsValid() && !m_margins.IsValid(); +} + // wxRichTextAttr void wxRichTextAttr::Copy(const wxRichTextAttr& attr) @@ -11849,6 +12146,18 @@ int wxRichTextProperties::Find(const wxString& name) const return -1; } +bool wxRichTextProperties::Remove(const wxString& name) +{ + int idx = Find(name); + if (idx != -1) + { + m_properties.RemoveAt(idx); + return true; + } + else + return false; +} + wxVariant* wxRichTextProperties::FindOrCreateProperty(const wxString& name) { int idx = Find(name); @@ -11937,6 +12246,26 @@ void wxRichTextProperties::SetProperty(const wxString& name, bool value) SetProperty(name, wxVariant(value, name)); } +void wxRichTextProperties::RemoveProperties(const wxRichTextProperties& properties) +{ + size_t i; + for (i = 0; i < properties.GetCount(); i++) + { + wxString name = properties.GetProperties()[i].GetName(); + if (HasProperty(name)) + Remove(name); + } +} + +void wxRichTextProperties::MergeProperties(const wxRichTextProperties& properties) +{ + size_t i; + for (i = 0; i < properties.GetCount(); i++) + { + SetProperty(properties.GetProperties()[i]); + } +} + wxRichTextObject* wxRichTextObjectAddress::GetObject(wxRichTextParagraphLayoutBox* topLevelContainer) const { if (m_address.GetCount() == 0) @@ -12083,6 +12412,107 @@ bool wxRichTextSelection::WithinSelection(const wxRichTextRange& range, const wx return false; } +IMPLEMENT_CLASS(wxRichTextDrawingHandler, wxObject) +IMPLEMENT_CLASS(wxRichTextDrawingContext, wxObject) + +bool wxRichTextDrawingContext::HasVirtualAttributes(wxRichTextObject* obj) const +{ + wxList::compatibility_iterator node = m_buffer->GetDrawingHandlers().GetFirst(); + while (node) + { + wxRichTextDrawingHandler *handler = (wxRichTextDrawingHandler*)node->GetData(); + if (handler->HasVirtualAttributes(obj)) + return true; + + node = node->GetNext(); + } + return false; +} + +wxRichTextAttr wxRichTextDrawingContext::GetVirtualAttributes(wxRichTextObject* obj) const +{ + wxRichTextAttr attr; + // We apply all handlers, so we can may combine several different attributes + wxList::compatibility_iterator node = m_buffer->GetDrawingHandlers().GetFirst(); + while (node) + { + wxRichTextDrawingHandler *handler = (wxRichTextDrawingHandler*)node->GetData(); + if (handler->HasVirtualAttributes(obj)) + { + bool success = handler->GetVirtualAttributes(attr, obj); + wxASSERT(success); + wxUnusedVar(success); + } + + node = node->GetNext(); + } + return attr; +} + +bool wxRichTextDrawingContext::ApplyVirtualAttributes(wxRichTextAttr& attr, wxRichTextObject* obj) const +{ + if (HasVirtualAttributes(obj)) + { + wxRichTextAttr a(GetVirtualAttributes(obj)); + attr.Apply(a); + return true; + } + else + return false; +} + +/// Adds a handler to the end +void wxRichTextBuffer::AddDrawingHandler(wxRichTextDrawingHandler *handler) +{ + sm_drawingHandlers.Append(handler); +} + +/// Inserts a handler at the front +void wxRichTextBuffer::InsertDrawingHandler(wxRichTextDrawingHandler *handler) +{ + sm_drawingHandlers.Insert( handler ); +} + +/// Removes a handler +bool wxRichTextBuffer::RemoveDrawingHandler(const wxString& name) +{ + wxRichTextDrawingHandler *handler = FindDrawingHandler(name); + if (handler) + { + sm_drawingHandlers.DeleteObject(handler); + delete handler; + return true; + } + else + return false; +} + +wxRichTextDrawingHandler* wxRichTextBuffer::FindDrawingHandler(const wxString& name) +{ + wxList::compatibility_iterator node = sm_drawingHandlers.GetFirst(); + while (node) + { + wxRichTextDrawingHandler *handler = (wxRichTextDrawingHandler*)node->GetData(); + if (handler->GetName().Lower() == name.Lower()) return handler; + + node = node->GetNext(); + } + return NULL; +} + +void wxRichTextBuffer::CleanUpDrawingHandlers() +{ + wxList::compatibility_iterator node = sm_drawingHandlers.GetFirst(); + while (node) + { + wxRichTextDrawingHandler* handler = (wxRichTextDrawingHandler*)node->GetData(); + wxList::compatibility_iterator next = node->GetNext(); + delete handler; + node = next; + } + + sm_drawingHandlers.Clear(); +} #endif // wxUSE_RICHTEXT