From 8db2e3ef1565e738ade7f63580951d1d040b9c29 Mon Sep 17 00:00:00 2001 From: Julian Smart Date: Tue, 17 Jan 2012 20:03:13 +0000 Subject: [PATCH] Added drawing context to allow 'virtual' (dynamic) attributes, for e.g. showing bookmarks without affecting the content git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@70378 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/richtext/richtextbuffer.h | 198 +++++++++--- interface/wx/richtext/richtextbuffer.h | 197 +++++++++--- src/richtext/richtextbuffer.cpp | 404 ++++++++++++++++--------- src/richtext/richtextctrl.cpp | 42 ++- src/richtext/richtextprint.cpp | 6 +- 5 files changed, 622 insertions(+), 225 deletions(-) diff --git a/include/wx/richtext/richtextbuffer.h b/include/wx/richtext/richtextbuffer.h index af21f78675..87c39441ec 100644 --- a/include/wx/richtext/richtextbuffer.h +++ b/include/wx/richtext/richtextbuffer.h @@ -130,6 +130,7 @@ class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextObjectList; class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextLine; class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextParagraph; class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextFileHandler; +class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextDrawingHandler; class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextStyleSheet; class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextListStyleDefinition; class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextEvent; @@ -2051,6 +2052,52 @@ public: wxRichTextParagraphLayoutBox* m_container; }; +/** + @class wxRichTextDrawingContext + + A class for passing information to drawing and measuring functions. + + @library{wxrichtext} + @category{richtext} + + @see wxRichTextBuffer, wxRichTextCtrl +*/ + +class WXDLLIMPEXP_RICHTEXT wxRichTextDrawingContext: public wxObject +{ + DECLARE_CLASS(wxRichTextDrawingContext) +public: + + /** + Pass the buffer to the context so the context can retrieve information + such as virtual attributes. + */ + wxRichTextDrawingContext(wxRichTextBuffer* buffer) { Init(); m_buffer = buffer; } + + void Init() { m_buffer = NULL; } + + /** + Does this object have virtual attributes? + Virtual attributes can be provided for visual cues without + affecting the actual styling. + */ + bool HasVirtualAttributes(wxRichTextObject* obj) const; + + /** + Returns the virtual attributes for this object. + Virtual attributes can be provided for visual cues without + affecting the actual styling. + */ + wxRichTextAttr GetVirtualAttributes(wxRichTextObject* obj) const; + + /** + Applies any virtual attributes relevant to this object. + */ + bool ApplyVirtualAttributes(wxRichTextAttr& attr, wxRichTextObject* obj) const; + + wxRichTextBuffer* m_buffer; +}; + /** @class wxRichTextObject @@ -2079,7 +2126,7 @@ public: Draw the item, within the given range. Some objects may ignore the range (for example paragraphs) while others must obey it (lines, to implement wrapping) */ - virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style) = 0; + virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style) = 0; /** Lay the item out at the specified position with the given size constraint. @@ -2087,7 +2134,7 @@ public: and @a parentRect is the container that is used to determine a relative size or position (for example if a text box must be 50% of the parent text box). */ - virtual bool Layout(wxDC& dc, const wxRect& rect, const wxRect& parentRect, int style) = 0; + virtual bool Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style) = 0; /** Hit-testing: returns a flag indicating hit test details, plus @@ -2106,12 +2153,12 @@ public: @return One of the ::wxRichTextHitTestFlags values. */ - virtual int HitTest(wxDC& dc, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); + virtual int HitTest(wxDC& dc, wxRichTextDrawingContext& context, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); /** Finds the absolute position and row height for the given character position. */ - virtual bool FindPosition(wxDC& WXUNUSED(dc), long WXUNUSED(index), wxPoint& WXUNUSED(pt), int* WXUNUSED(height), bool WXUNUSED(forceLineStart)) { return false; } + virtual bool FindPosition(wxDC& WXUNUSED(dc), wxRichTextDrawingContext& WXUNUSED(context), long WXUNUSED(index), wxPoint& WXUNUSED(pt), int* WXUNUSED(height), bool WXUNUSED(forceLineStart)) { return false; } /** Returns the best size, i.e. the ideal starting size for this object irrespective @@ -2125,7 +2172,7 @@ public: is invalid for this object. */ - virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const = 0; + virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const = 0; /** Do a split from @a pos, returning an object containing the second part, and setting @@ -2421,7 +2468,7 @@ public: Calculates the available content space in the given rectangle, given the margins, border and padding specified in the object's attributes. */ - virtual wxRect GetAvailableContentArea(wxDC& dc, const wxRect& outerRect) const; + virtual wxRect GetAvailableContentArea(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& outerRect) const; /** Lays out the object first with a given amount of space, and then if no width was specified in attr, @@ -2431,7 +2478,7 @@ public: in a previous layout pass to @a availableParentSpace, but should have a width of 50% of @a availableContainerSpace. (If these two rects were the same, a 2nd pass could see the object getting too small.) */ - virtual bool LayoutToBestSize(wxDC& dc, wxRichTextBuffer* buffer, + virtual bool LayoutToBestSize(wxDC& dc, wxRichTextDrawingContext& context, wxRichTextBuffer* buffer, const wxRichTextAttr& parentAttr, const wxRichTextAttr& attr, const wxRect& availableParentSpace, const wxRect& availableContainerSpace, int style); @@ -2637,9 +2684,9 @@ public: // Overridables - virtual int HitTest(wxDC& dc, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); + virtual int HitTest(wxDC& dc, wxRichTextDrawingContext& context, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); - virtual bool FindPosition(wxDC& dc, long index, wxPoint& pt, int* height, bool forceLineStart); + virtual bool FindPosition(wxDC& dc, wxRichTextDrawingContext& context, long index, wxPoint& pt, int* height, bool forceLineStart); virtual void CalculateRange(long start, long& end); @@ -2647,7 +2694,7 @@ public: virtual wxString GetTextForRange(const wxRichTextRange& range) const; - virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; + virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; virtual void Dump(wxTextOutputStream& stream); @@ -2752,13 +2799,13 @@ public: // Overridables - virtual int HitTest(wxDC& dc, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); + virtual int HitTest(wxDC& dc, wxRichTextDrawingContext& context, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); - virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); + virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); - virtual bool Layout(wxDC& dc, const wxRect& rect, const wxRect& parentRect, int style); + virtual bool Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style); - virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; + virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; virtual bool DeleteRange(const wxRichTextRange& range); @@ -2852,7 +2899,7 @@ public: /** Draws the floating objects in this buffer. */ - void DrawFloats(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); + void DrawFloats(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); /** Moves an anchored object to another paragraph. @@ -3344,7 +3391,7 @@ public: // Overridables - virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); + virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); virtual wxString GetXMLNodeName() const { return wxT("textbox"); } @@ -3531,15 +3578,15 @@ public: // Overridables - virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); + virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); - virtual bool Layout(wxDC& dc, const wxRect& rect, const wxRect& parentRect, int style); + virtual bool Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style); - virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; + virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; - virtual bool FindPosition(wxDC& dc, long index, wxPoint& pt, int* height, bool forceLineStart); + virtual bool FindPosition(wxDC& dc, wxRichTextDrawingContext& context, long index, wxPoint& pt, int* height, bool forceLineStart); - virtual int HitTest(wxDC& dc, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); + virtual int HitTest(wxDC& dc, wxRichTextDrawingContext& context, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); virtual void CalculateRange(long start, long& end); @@ -3604,7 +3651,7 @@ public: Finds a suitable wrap position. @a wrapPosition is the last position in the line to the left of the split. */ - bool FindWrapPosition(const wxRichTextRange& range, wxDC& dc, int availableSpace, long& wrapPosition, wxArrayInt* partialExtents); + bool FindWrapPosition(const wxRichTextRange& range, wxDC& dc, wxRichTextDrawingContext& context, int availableSpace, long& wrapPosition, wxArrayInt* partialExtents); /** Finds the object at the given position. @@ -3660,7 +3707,7 @@ public: /** Lays out the floating objects. */ - void LayoutFloat(wxDC& dc, const wxRect& rect, int style, wxRichTextFloatCollector* floatCollector); + void LayoutFloat(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, int style, wxRichTextFloatCollector* floatCollector); protected: @@ -3702,11 +3749,11 @@ public: // Overridables - virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); + virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); - virtual bool Layout(wxDC& dc, const wxRect& rect, const wxRect& parentRect, int style); + virtual bool Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style); - virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; + virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; virtual wxString GetTextForRange(const wxRichTextRange& range) const; @@ -3978,11 +4025,11 @@ public: // Overridables - virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); + virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); - virtual bool Layout(wxDC& dc, const wxRect& rect, const wxRect& parentRect, int style); + virtual bool Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style); - virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; + virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; /** Returns the 'natural' size for this object - the image size. @@ -4526,7 +4573,7 @@ public: // Implementation - virtual int HitTest(wxDC& dc, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); + virtual int HitTest(wxDC& dc, wxRichTextDrawingContext& context, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); /** Copies the buffer. @@ -4651,6 +4698,36 @@ public: */ static void InitStandardHandlers(); + /** + Returns the drawing handlers. + */ + static wxList& GetDrawingHandlers() { return sm_drawingHandlers; } + + /** + Adds a drawing handler to the end. + */ + static void AddDrawingHandler(wxRichTextDrawingHandler *handler); + + /** + Inserts a drawing handler at the front. + */ + static void InsertDrawingHandler(wxRichTextDrawingHandler *handler); + + /** + Removes a drawing handler. + */ + static bool RemoveDrawingHandler(const wxString& name); + + /** + Finds a drawing handler by name. + */ + static wxRichTextDrawingHandler *FindDrawingHandler(const wxString& name); + + /** + Clean up drawing handlers. + */ + static void CleanUpDrawingHandlers(); + /** Returns the renderer object. */ @@ -4734,6 +4811,9 @@ protected: /// File handlers static wxList sm_handlers; + /// Drawing handlers + static wxList sm_drawingHandlers; + /// Renderer static wxRichTextRenderer* sm_renderer; @@ -4773,7 +4853,7 @@ public: // Overridables - virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); + virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); virtual wxString GetXMLNodeName() const { return wxT("cell"); } @@ -4824,13 +4904,13 @@ public: // Overridables - virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); + virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); virtual wxString GetXMLNodeName() const { return wxT("table"); } - virtual bool Layout(wxDC& dc, const wxRect& rect, const wxRect& parentRect, int style); + virtual bool Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style); - virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; + virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; virtual bool DeleteRange(const wxRichTextRange& range); @@ -4848,7 +4928,7 @@ public: virtual bool ExportXML(wxXmlNode* parent, wxRichTextXMLHandler* handler); #endif - virtual bool FindPosition(wxDC& dc, long index, wxPoint& pt, int* height, bool forceLineStart); + virtual bool FindPosition(wxDC& dc, wxRichTextDrawingContext& context, long index, wxPoint& pt, int* height, bool forceLineStart); virtual void CalculateRange(long start, long& end); @@ -5513,6 +5593,54 @@ protected: }; +/** + @class wxRichTextDrawingHandler + + The base class for custom drawing handlers. + Currently, drawing handlers can provide virtual handlers. + + @library{wxrichtext} + @category{richtext} + + @see wxRichTextBuffer, wxRichTextCtrl +*/ + +class WXDLLIMPEXP_RICHTEXT wxRichTextDrawingHandler: public wxObject +{ + DECLARE_CLASS(wxRichTextDrawingHandler) +public: + /** + Creates a drawing handler object. + */ + wxRichTextDrawingHandler(const wxString& name = wxEmptyString) + : m_name(name) + { } + + /** + Returns @true if this object has virtual attributes that we can provide. + */ + virtual bool HasVirtualAttributes(wxRichTextObject* obj) const = 0; + + /** + Provides virtual attributes that we can provide. + */ + virtual bool GetVirtualAttributes(wxRichTextAttr& attr, wxRichTextObject* obj) const = 0; + + /** + Sets the name of the nandler. + */ + void SetName(const wxString& name) { m_name = name; } + + /** + Returns the name of the nandler. + */ + wxString GetName() const { return m_name; } + +protected: + + wxString m_name; +}; + #if wxUSE_DATAOBJ /** diff --git a/interface/wx/richtext/richtextbuffer.h b/interface/wx/richtext/richtextbuffer.h index 0fbfc691cf..86a7baf5ef 100644 --- a/interface/wx/richtext/richtextbuffer.h +++ b/interface/wx/richtext/richtextbuffer.h @@ -1935,6 +1935,52 @@ public: wxRichTextParagraphLayoutBox* m_container; }; +/** + @class wxRichTextDrawingContext + + A class for passing information to drawing and measuring functions. + + @library{wxrichtext} + @category{richtext} + + @see wxRichTextBuffer, wxRichTextCtrl +*/ + +class WXDLLIMPEXP_RICHTEXT wxRichTextDrawingContext: public wxObject +{ + DECLARE_CLASS(wxRichTextDrawingContext) +public: + + /** + Pass the buffer to the context so the context can retrieve information + such as virtual attributes. + */ + wxRichTextDrawingContext(wxRichTextBuffer* buffer) { Init(); m_buffer = buffer; } + + void Init() { m_buffer = NULL; } + + /** + Does this object have virtual attributes? + Virtual attributes can be provided for visual cues without + affecting the actual styling. + */ + bool HasVirtualAttributes(wxRichTextObject* obj) const; + + /** + Returns the virtual attributes for this object. + Virtual attributes can be provided for visual cues without + affecting the actual styling. + */ + wxRichTextAttr GetVirtualAttributes(wxRichTextObject* obj) const; + + /** + Applies any virtual attributes relevant to this object. + */ + bool ApplyVirtualAttributes(wxRichTextAttr& attr, wxRichTextObject* obj) const; + + wxRichTextBuffer* m_buffer; +}; + /** @class wxRichTextObject @@ -1963,7 +2009,7 @@ public: Draw the item, within the given range. Some objects may ignore the range (for example paragraphs) while others must obey it (lines, to implement wrapping) */ - virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style) = 0; + virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style) = 0; /** Lay the item out at the specified position with the given size constraint. @@ -1971,7 +2017,7 @@ public: and @a parentRect is the container that is used to determine a relative size or position (for example if a text box must be 50% of the parent text box). */ - virtual bool Layout(wxDC& dc, const wxRect& rect, const wxRect& parentRect, int style) = 0; + virtual bool Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style) = 0; /** Hit-testing: returns a flag indicating hit test details, plus @@ -1986,12 +2032,12 @@ public: @return One of the ::wxRichTextHitTestFlags values. */ - virtual int HitTest(wxDC& dc, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); + virtual int HitTest(wxDC& dc, wxRichTextDrawingContext& context, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); /** Finds the absolute position and row height for the given character position. */ - virtual bool FindPosition(wxDC& WXUNUSED(dc), long WXUNUSED(index), wxPoint& WXUNUSED(pt), int* WXUNUSED(height), bool WXUNUSED(forceLineStart)) { return false; } + virtual bool FindPosition(wxDC& WXUNUSED(dc), wxRichTextDrawingContext& WXUNUSED(context), long WXUNUSED(index), wxPoint& WXUNUSED(pt), int* WXUNUSED(height), bool WXUNUSED(forceLineStart)) { return false; } /** Returns the best size, i.e. the ideal starting size for this object irrespective @@ -2005,7 +2051,7 @@ public: is invalid for this object. */ - virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const = 0; + virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const = 0; /** Do a split from @a pos, returning an object containing the second part, and setting @@ -2301,7 +2347,7 @@ public: Calculates the available content space in the given rectangle, given the margins, border and padding specified in the object's attributes. */ - virtual wxRect GetAvailableContentArea(wxDC& dc, const wxRect& outerRect) const; + virtual wxRect GetAvailableContentArea(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& outerRect) const; /** Lays out the object first with a given amount of space, and then if no width was specified in attr, @@ -2311,7 +2357,7 @@ public: in a previous layout pass to @a availableParentSpace, but should have a width of 50% of @a availableContainerSpace. (If these two rects were the same, a 2nd pass could see the object getting too small.) */ - virtual bool LayoutToBestSize(wxDC& dc, wxRichTextBuffer* buffer, + virtual bool LayoutToBestSize(wxDC& dc, wxRichTextDrawingContext& context, wxRichTextBuffer* buffer, const wxRichTextAttr& parentAttr, const wxRichTextAttr& attr, const wxRect& availableParentSpace, const wxRect& availableContainerSpace, int style); @@ -2517,9 +2563,9 @@ public: // Overridables - virtual int HitTest(wxDC& dc, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); + virtual int HitTest(wxDC& dc, wxRichTextDrawingContext& context, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); - virtual bool FindPosition(wxDC& dc, long index, wxPoint& pt, int* height, bool forceLineStart); + virtual bool FindPosition(wxDC& dc, wxRichTextDrawingContext& context, long index, wxPoint& pt, int* height, bool forceLineStart); virtual void CalculateRange(long start, long& end); @@ -2527,7 +2573,7 @@ public: virtual wxString GetTextForRange(const wxRichTextRange& range) const; - virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; + virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; virtual void Dump(wxTextOutputStream& stream); @@ -2632,13 +2678,13 @@ public: // Overridables - virtual int HitTest(wxDC& dc, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); + virtual int HitTest(wxDC& dc, wxRichTextDrawingContext& context, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); - virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); + virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); - virtual bool Layout(wxDC& dc, const wxRect& rect, const wxRect& parentRect, int style); + virtual bool Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style); - virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; + virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; virtual bool DeleteRange(const wxRichTextRange& range); @@ -2733,7 +2779,7 @@ public: /** Draws the floating objects in this buffer. */ - void DrawFloats(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); + void DrawFloats(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); /** Moves an anchored object to another paragraph. @@ -3225,7 +3271,7 @@ public: // Overridables - virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); + virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); virtual wxString GetXMLNodeName() const { return wxT("textbox"); } @@ -3412,15 +3458,15 @@ public: // Overridables - virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); + virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); - virtual bool Layout(wxDC& dc, const wxRect& rect, const wxRect& parentRect, int style); + virtual bool Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style); - virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; + virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; - virtual bool FindPosition(wxDC& dc, long index, wxPoint& pt, int* height, bool forceLineStart); + virtual bool FindPosition(wxDC& dc, wxRichTextDrawingContext& context, long index, wxPoint& pt, int* height, bool forceLineStart); - virtual int HitTest(wxDC& dc, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); + virtual int HitTest(wxDC& dc, wxRichTextDrawingContext& context, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); virtual void CalculateRange(long start, long& end); @@ -3485,7 +3531,7 @@ public: Finds a suitable wrap position. @a wrapPosition is the last position in the line to the left of the split. */ - bool FindWrapPosition(const wxRichTextRange& range, wxDC& dc, int availableSpace, long& wrapPosition, wxArrayInt* partialExtents); + bool FindWrapPosition(const wxRichTextRange& range, wxDC& dc, wxRichTextDrawingContext& context, int availableSpace, long& wrapPosition, wxArrayInt* partialExtents); /** Finds the object at the given position. @@ -3541,7 +3587,7 @@ public: /** Lays out the floating objects. */ - void LayoutFloat(wxDC& dc, const wxRect& rect, int style, wxRichTextFloatCollector* floatCollector); + void LayoutFloat(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, int style, wxRichTextFloatCollector* floatCollector); protected: @@ -3583,11 +3629,11 @@ public: // Overridables - virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); + virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); - virtual bool Layout(wxDC& dc, const wxRect& rect, const wxRect& parentRect, int style); + virtual bool Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style); - virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; + virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; virtual wxString GetTextForRange(const wxRichTextRange& range) const; @@ -3859,11 +3905,11 @@ public: // Overridables - virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); + virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); - virtual bool Layout(wxDC& dc, const wxRect& rect, const wxRect& parentRect, int style); + virtual bool Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style); - virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; + virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; /** Returns the 'natural' size for this object - the image size. @@ -4407,7 +4453,7 @@ public: // Implementation - virtual int HitTest(wxDC& dc, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); + virtual int HitTest(wxDC& dc, wxRichTextDrawingContext& context, const wxPoint& pt, long& textPosition, wxRichTextObject** obj, wxRichTextObject** contextObj, int flags = 0); /** Copies the buffer. @@ -4532,6 +4578,36 @@ public: */ static void InitStandardHandlers(); + /** + Returns the drawing handlers. + */ + static wxList& GetDrawingHandlers() { return sm_drawingHandlers; } + + /** + Adds a drawing handler to the end. + */ + static void AddDrawingHandler(wxRichTextDrawingHandler *handler); + + /** + Inserts a drawing handler at the front. + */ + static void InsertDrawingHandler(wxRichTextDrawingHandler *handler); + + /** + Removes a drawing handler. + */ + static bool RemoveDrawingHandler(const wxString& name); + + /** + Finds a drawing handler by name. + */ + static wxRichTextDrawingHandler *FindDrawingHandler(const wxString& name); + + /** + Clean up drawing handlers. + */ + static void CleanUpDrawingHandlers(); + /** Returns the renderer object. */ @@ -4615,6 +4691,9 @@ protected: /// File handlers static wxList sm_handlers; + /// Drawing handlers + static wxList sm_drawingHandlers; + /// Renderer static wxRichTextRenderer* sm_renderer; @@ -4654,7 +4733,7 @@ public: // Overridables - virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); + virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); virtual wxString GetXMLNodeName() const { return wxT("cell"); } @@ -4705,13 +4784,13 @@ public: // Overridables - virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); + virtual bool Draw(wxDC& dc, wxRichTextDrawingContext& context, const wxRichTextRange& range, const wxRichTextSelection& selection, const wxRect& rect, int descent, int style); virtual wxString GetXMLNodeName() const { return wxT("table"); } - virtual bool Layout(wxDC& dc, const wxRect& rect, const wxRect& parentRect, int style); + virtual bool Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style); - virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; + virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, wxRichTextDrawingContext& context, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const; virtual bool DeleteRange(const wxRichTextRange& range); @@ -4729,7 +4808,7 @@ public: virtual bool ExportXML(wxXmlNode* parent, wxRichTextXMLHandler* handler); #endif - virtual bool FindPosition(wxDC& dc, long index, wxPoint& pt, int* height, bool forceLineStart); + virtual bool FindPosition(wxDC& dc, wxRichTextDrawingContext& context, long index, wxPoint& pt, int* height, bool forceLineStart); virtual void CalculateRange(long start, long& end); @@ -5393,6 +5472,54 @@ protected: }; +/** + @class wxRichTextDrawingHandler + + The base class for custom drawing handlers. + Currently, drawing handlers can provide virtual handlers. + + @library{wxrichtext} + @category{richtext} + + @see wxRichTextBuffer, wxRichTextCtrl +*/ + +class WXDLLIMPEXP_RICHTEXT wxRichTextDrawingHandler: public wxObject +{ + DECLARE_CLASS(wxRichTextDrawingHandler) +public: + /** + Creates a drawing handler object. + */ + wxRichTextDrawingHandler(const wxString& name = wxEmptyString) + : m_name(name) + { } + + /** + Returns @true if this object has virtual attributes that we can provide. + */ + virtual bool HasVirtualAttributes(wxRichTextObject* obj) const = 0; + + /** + Provides virtual attributes that we can provide. + */ + virtual bool GetVirtualAttributes(wxRichTextAttr& attr, wxRichTextObject* obj) const = 0; + + /** + Sets the name of the nandler. + */ + void SetName(const wxString& name) { m_name = name; } + + /** + Returns the name of the nandler. + */ + wxString GetName() const { return m_name; } + +protected: + + wxString m_name; +}; + #if wxUSE_DATAOBJ /** diff --git a/src/richtext/richtextbuffer.cpp b/src/richtext/richtextbuffer.cpp index 269a15ddd2..1303fe8379 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; } @@ -1038,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; @@ -1058,14 +1060,14 @@ 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, +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, availableContainerSpace); wxRect originalAvailableRect = availableChildRect; - Layout(dc, availableChildRect, availableContainerSpace, style); + Layout(dc, context, availableChildRect, availableContainerSpace, style); wxSize maxSize = GetMaxSize(); @@ -1087,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, availableContainerSpace, style); + Layout(dc, context, availableChildRect, availableContainerSpace, style); } /* @@ -1227,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; @@ -1240,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; } @@ -1258,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) @@ -1269,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(); @@ -1479,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; @@ -1535,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; @@ -1736,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; @@ -1755,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) @@ -1771,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; @@ -1786,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) { @@ -1813,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(); @@ -1822,7 +1827,7 @@ bool wxRichTextParagraphLayoutBox::Draw(wxDC& dc, const wxRichTextRange& range, } /// Lay the item out -bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, const wxRect& parentRect, int style) +bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& parentRect, int style) { SetPosition(rect.GetPosition()); @@ -1832,6 +1837,9 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, const wx 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 @@ -1840,7 +1848,7 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, const wx 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, @@ -1855,11 +1863,11 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, const wx } 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; @@ -1872,8 +1880,8 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, const wx 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(); @@ -1952,8 +1960,8 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, const wx { // 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, rect, 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; @@ -1986,8 +1994,8 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, const wx { // 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, rect, 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); } @@ -2018,9 +2026,9 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, const wx else maxHeight = 0; // topMargin + bottomMargin; - if (GetAttributes().GetTextBoxAttr().GetSize().GetWidth().IsValid()) + if (attr.GetTextBoxAttr().GetSize().GetWidth().IsValid()) { - wxRect r = AdjustAvailableSpace(dc, GetBuffer(), wxRichTextAttr() /* not used */, GetAttributes(), parentRect, parentRect); + wxRect r = AdjustAvailableSpace(dc, GetBuffer(), wxRichTextAttr() /* not used */, attr, parentRect, parentRect); int w = r.GetWidth(); // Convert external to content rect @@ -2037,7 +2045,7 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, const wx { 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()); } @@ -2045,7 +2053,7 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, const wx { 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()); } @@ -2053,22 +2061,22 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, const wx { 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; } @@ -2096,7 +2104,7 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, const wx } /// 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; @@ -2155,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); @@ -4329,7 +4337,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; @@ -4339,9 +4347,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) @@ -4351,7 +4360,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) @@ -4459,13 +4468,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 ++; @@ -4504,16 +4513,17 @@ static int wxRichTextGetRangeWidth(const wxRichTextParagraph& para, const wxRich } /// Lay the item out -bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, const wxRect& parentRect, 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(); @@ -4568,7 +4578,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, const wxRect& par 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) @@ -4576,7 +4586,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, const wxRect& par wxRichTextObject* child = node->GetData(); //child->SetCachedSize(wxDefaultSize); - child->Layout(dc, rect, style); + child->Layout(dc, context, rect, style); node = node->GetNext(); } @@ -4643,15 +4653,15 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, const wxRect& par // 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, parentRect, 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); } } @@ -4668,10 +4678,10 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, const wxRect& par { #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 } @@ -4727,8 +4737,8 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, const wxRect& par // 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, parentRect, style); + child->LayoutToBestSize(dc, context, buffer, + attr, child->GetAttributes(), availableRect, parentRect, style); childSize = child->GetCachedSize(); childDescent = child->GetDescent(); //child->SetPosition(availableRect.GetPosition()); @@ -4738,7 +4748,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, const wxRect& par 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 @@ -4781,7 +4791,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, const wxRect& par // 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(); @@ -4809,12 +4819,12 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, const wxRect& par 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); @@ -4902,7 +4912,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, const wxRect& par { 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()); } @@ -4912,7 +4922,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, const wxRect& par { wxRect marginRect, borderRect, contentRect, paddingRect, outlineRect; contentRect = wxRect(wxPoint(0, 0), wxSize(paraSize.x + wxMax(leftIndent, leftIndent + leftSubIndent) + rightIndent, currentPosition.y + spaceAfterPara)); - GetBoxRects(dc, buffer, GetAttributes(), marginRect, borderRect, contentRect, paddingRect, outlineRect); + GetBoxRects(dc, buffer, attr, marginRect, borderRect, contentRect, paddingRect, outlineRect); SetMaxSize(marginRect.GetSize()); } @@ -4939,7 +4949,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, const wxRect& par 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()); } @@ -5000,13 +5010,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; @@ -5097,7 +5107,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; @@ -5185,7 +5195,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; @@ -5257,7 +5267,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; @@ -5280,7 +5290,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) { @@ -5356,7 +5366,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; @@ -5374,7 +5384,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; @@ -5391,7 +5401,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; } @@ -5402,7 +5412,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; } @@ -5446,7 +5456,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; @@ -5484,7 +5494,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; @@ -5686,7 +5696,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; @@ -5728,7 +5738,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; @@ -5737,13 +5747,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; } @@ -5754,7 +5764,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) { @@ -5957,7 +5967,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) @@ -5967,7 +5977,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()) @@ -6096,12 +6106,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 @@ -6398,11 +6409,11 @@ bool wxRichTextPlainText::DrawTabbedString(wxDC& dc, const wxRichTextAttr& attr, } /// Lay the item out -bool wxRichTextPlainText::Layout(wxDC& dc, const wxRect& WXUNUSED(rect), const wxRect& WXUNUSED(parentRect), 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); @@ -6419,7 +6430,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; @@ -6430,6 +6441,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 @@ -6616,6 +6628,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); @@ -6667,7 +6680,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. @@ -6719,6 +6732,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; @@ -7963,9 +7977,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; @@ -8142,7 +8156,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; @@ -8152,7 +8166,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 @@ -8186,9 +8200,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 @@ -8282,9 +8296,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); @@ -8295,7 +8309,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, const wxRect& WXUNUSED(parentRect), int style) +bool wxRichTextTable::Layout(wxDC& dc, wxRichTextDrawingContext& context, const wxRect& rect, const wxRect& WXUNUSED(parentRect), int style) { SetPosition(rect.GetPosition()); @@ -8307,17 +8321,20 @@ bool wxRichTextTable::Layout(wxDC& dc, const wxRect& rect, const wxRect& WXUNUSE 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; @@ -8328,17 +8345,17 @@ bool wxRichTextTable::Layout(wxDC& dc, const wxRect& rect, const wxRect& WXUNUSE // Get internal padding int paddingLeft = 0, paddingTop = 0; - if (GetAttributes().GetTextBoxAttr().GetPadding().GetLeft().IsValid()) - paddingLeft = converter.GetPixels(GetAttributes().GetTextBoxAttr().GetPadding().GetLeft()); - if (GetAttributes().GetTextBoxAttr().GetPadding().GetTop().IsValid()) - paddingTop = converter.GetPixels(GetAttributes().GetTextBoxAttr().GetPadding().GetTop()); + 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; @@ -8512,7 +8529,7 @@ bool wxRichTextTable::Layout(wxDC& dc, const wxRect& rect, const wxRect& WXUNUSE // Lay out cell to find min/max widths cell->Invalidate(wxRICHTEXT_ALL); - cell->Layout(dc, availableSpace, availableSpace, style); + cell->Layout(dc, context, availableSpace, availableSpace, style); if (colSpan == 1) { @@ -8851,7 +8868,7 @@ bool wxRichTextTable::Layout(wxDC& dc, const wxRect& rect, const wxRect& WXUNUSE // Lay out cell cell->Invalidate(wxRICHTEXT_ALL); - cell->Layout(dc, availableCellSpace, availableSpace, style); + cell->Layout(dc, context, availableCellSpace, availableSpace, style); // TODO: use GetCachedSize().x to compute 'natural' size @@ -8872,7 +8889,7 @@ bool wxRichTextTable::Layout(wxDC& dc, const wxRect& rect, const wxRect& WXUNUSE wxRect availableCellSpace = wxRect(cell->GetPosition(), wxSize(actualWidths[i], maxCellHeight)); // Lay out cell with new height cell->Invalidate(wxRICHTEXT_ALL); - cell->Layout(dc, availableCellSpace, availableSpace, style); + cell->Layout(dc, context, availableCellSpace, availableSpace, style); // Make sure the cell size really is the appropriate size, // not the calculated box size @@ -8891,7 +8908,7 @@ bool wxRichTextTable::Layout(wxDC& dc, const wxRect& rect, const wxRect& WXUNUSE { 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()); } @@ -8921,14 +8938,14 @@ bool wxRichTextTable::Layout(wxDC& dc, const wxRect& rect, const wxRect& WXUNUSE } // 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; @@ -9006,9 +9023,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. @@ -9360,6 +9377,7 @@ public: void OnExit() { wxRichTextBuffer::CleanUpHandlers(); + wxRichTextBuffer::CleanUpDrawingHandlers(); wxRichTextDecimalToRoman(-1); wxRichTextParagraph::ClearDefaultTabs(); wxRichTextCtrl::ClearAvailableFontNames(); @@ -10094,7 +10112,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; @@ -10104,7 +10122,10 @@ bool wxRichTextImage::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichT if (!LoadImageCache(dc)) return false; - DrawBoxAttributes(dc, GetBuffer(), GetAttributes(), wxRect(rect.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()); @@ -10115,7 +10136,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); @@ -10132,7 +10153,7 @@ bool wxRichTextImage::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichT } /// Lay the item out -bool wxRichTextImage::Layout(wxDC& dc, const wxRect& rect, const wxRect& WXUNUSED(parentRect), 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; @@ -10140,7 +10161,11 @@ bool wxRichTextImage::Layout(wxDC& dc, const wxRect& rect, const wxRect& WXUNUSE 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(); @@ -10154,7 +10179,7 @@ bool wxRichTextImage::Layout(wxDC& dc, const wxRect& rect, const wxRect& WXUNUSE /// 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; @@ -10167,10 +10192,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(); @@ -12371,6 +12399,106 @@ 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); + } + + 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 diff --git a/src/richtext/richtextctrl.cpp b/src/richtext/richtextctrl.cpp index 626cd1357a..9395714d2d 100644 --- a/src/richtext/richtextctrl.cpp +++ b/src/richtext/richtextctrl.cpp @@ -445,9 +445,10 @@ void wxRichTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) drawingArea.SetPosition(GetLogicalPoint(drawingArea.GetPosition())); wxRect availableSpace(GetClientSize()); + wxRichTextDrawingContext context(& GetBuffer()); if (GetBuffer().IsDirty()) { - GetBuffer().Layout(dc, availableSpace, availableSpace, wxRICHTEXT_FIXED_WIDTH|wxRICHTEXT_VARIABLE_HEIGHT); + GetBuffer().Layout(dc, context, availableSpace, availableSpace, wxRICHTEXT_FIXED_WIDTH|wxRICHTEXT_VARIABLE_HEIGHT); GetBuffer().Invalidate(wxRICHTEXT_NONE); SetupScrollbars(); } @@ -464,7 +465,7 @@ void wxRichTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) if ((GetExtraStyle() & wxRICHTEXT_EX_NO_GUIDELINES) == 0) flags |= wxRICHTEXT_DRAW_GUIDELINES; - GetBuffer().Draw(dc, GetBuffer().GetOwnRange(), GetSelection(), drawingArea, 0 /* descent */, flags); + GetBuffer().Draw(dc, context, GetBuffer().GetOwnRange(), GetSelection(), drawingArea, 0 /* descent */, flags); dc.DestroyClippingRegion(); @@ -573,7 +574,8 @@ void wxRichTextCtrl::OnLeftClick(wxMouseEvent& event) long position = 0; wxRichTextObject* hitObj = NULL; wxRichTextObject* contextObj = NULL; - int hit = GetBuffer().HitTest(dc, event.GetLogicalPosition(dc), position, & hitObj, & contextObj); + wxRichTextDrawingContext context(& GetBuffer()); + int hit = GetBuffer().HitTest(dc, context, event.GetLogicalPosition(dc), position, & hitObj, & contextObj); #if wxUSE_DRAG_AND_DROP // If there's no selection, or we're not inside it, this isn't an attempt to initiate Drag'n'Drop @@ -639,8 +641,9 @@ void wxRichTextCtrl::OnLeftUp(wxMouseEvent& event) wxPoint logicalPt = event.GetLogicalPosition(dc); wxRichTextObject* hitObj = NULL; wxRichTextObject* contextObj = NULL; + wxRichTextDrawingContext context(& GetBuffer()); // Only get objects at this level, not nested, because otherwise we couldn't swipe text at a single level. - int hit = GetFocusObject()->HitTest(dc, logicalPt, position, & hitObj, & contextObj, wxRICHTEXT_HITTEST_NO_NESTED_OBJECTS); + int hit = GetFocusObject()->HitTest(dc, context, logicalPt, position, & hitObj, & contextObj, wxRICHTEXT_HITTEST_NO_NESTED_OBJECTS); #if wxUSE_DRAG_AND_DROP if (m_preDrag) @@ -652,7 +655,7 @@ void wxRichTextCtrl::OnLeftUp(wxMouseEvent& event) long position = 0; wxRichTextObject* hitObj = NULL; wxRichTextObject* contextObj = NULL; - int hit = GetBuffer().HitTest(dc, event.GetLogicalPosition(dc), position, & hitObj, & contextObj); + int hit = GetBuffer().HitTest(dc, context, event.GetLogicalPosition(dc), position, & hitObj, & contextObj); wxRichTextParagraphLayoutBox* oldFocusObject = GetFocusObject(); wxRichTextParagraphLayoutBox* container = wxDynamicCast(contextObj, wxRichTextParagraphLayoutBox); if (container && container != GetFocusObject() && container->AcceptsFocus()) @@ -823,7 +826,8 @@ void wxRichTextCtrl::OnMoveMouse(wxMouseEvent& event) flags = wxRICHTEXT_HITTEST_NO_NESTED_OBJECTS; container = GetFocusObject(); } - int hit = container->HitTest(dc, logicalPt, position, & hitObj, & contextObj, flags); + wxRichTextDrawingContext context(& GetBuffer()); + int hit = container->HitTest(dc, context, logicalPt, position, & hitObj, & contextObj, flags); // See if we need to change the cursor @@ -857,7 +861,8 @@ void wxRichTextCtrl::OnMoveMouse(wxMouseEvent& event) // Check for dragging across multiple containers long position2 = 0; wxRichTextObject* hitObj2 = NULL, *contextObj2 = NULL; - int hit2 = GetBuffer().HitTest(dc, logicalPt, position2, & hitObj2, & contextObj2, 0); + wxRichTextDrawingContext context(& GetBuffer()); + int hit2 = GetBuffer().HitTest(dc, context, logicalPt, position2, & hitObj2, & contextObj2, 0); if (hit2 != wxRICHTEXT_HITTEST_NONE && !(hit2 & wxRICHTEXT_HITTEST_OUTSIDE) && hitObj2 && hitObj != hitObj2) { // See if we can find a common ancestor @@ -945,7 +950,8 @@ void wxRichTextCtrl::OnRightClick(wxMouseEvent& event) wxPoint logicalPt = event.GetLogicalPosition(dc); wxRichTextObject* hitObj = NULL; wxRichTextObject* contextObj = NULL; - int hit = GetFocusObject()->HitTest(dc, logicalPt, position, & hitObj, & contextObj); + wxRichTextDrawingContext context(& GetBuffer()); + int hit = GetFocusObject()->HitTest(dc, context, logicalPt, position, & hitObj, & contextObj); if (hitObj && hitObj->GetContainer() != GetFocusObject()) { @@ -1397,7 +1403,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) } } -bool wxRichTextCtrl::ProcessMouseMovement(wxRichTextParagraphLayoutBox* container, wxRichTextObject* obj, long position, const wxPoint& pos) +bool wxRichTextCtrl::ProcessMouseMovement(wxRichTextParagraphLayoutBox* container, wxRichTextObject* WXUNUSED(obj), long position, const wxPoint& WXUNUSED(pos)) { wxRichTextAttr attr; if (container && GetStyle(position, attr, container)) @@ -2020,7 +2026,8 @@ bool wxRichTextCtrl::MoveDown(int noLines, int flags) wxRichTextObject* hitObj = NULL; wxRichTextObject* contextObj = NULL; - int hitTest = container->HitTest(dc, pt, newPos, & hitObj, & contextObj, hitTestFlags); + wxRichTextDrawingContext context(& GetBuffer()); + int hitTest = container->HitTest(dc, context, pt, newPos, & hitObj, & contextObj, hitTestFlags); if (hitObj && ((hitTest & wxRICHTEXT_HITTEST_NONE) == 0) && @@ -2734,7 +2741,8 @@ wxRichTextCtrl::HitTest(const wxPoint& pt, wxRichTextObject* hitObj = NULL; wxRichTextObject* contextObj = NULL; - int hit = ((wxRichTextCtrl*)this)->GetFocusObject()->HitTest(dc, pt2, *pos, & hitObj, & contextObj, wxRICHTEXT_HITTEST_NO_NESTED_OBJECTS); + wxRichTextDrawingContext context((wxRichTextBuffer*) & GetBuffer()); + int hit = ((wxRichTextCtrl*)this)->GetFocusObject()->HitTest(dc, context, pt2, *pos, & hitObj, & contextObj, wxRICHTEXT_HITTEST_NO_NESTED_OBJECTS); if ((hit & wxRICHTEXT_HITTEST_BEFORE) && (hit & wxRICHTEXT_HITTEST_OUTSIDE)) return wxTE_HT_BEFORE; @@ -2756,7 +2764,8 @@ wxRichTextCtrl::FindContainerAtPoint(const wxPoint pt, long& position, int& hit, wxPoint logicalPt = GetLogicalPoint(pt); wxRichTextObject* contextObj = NULL; - hit = GetBuffer().HitTest(dc, logicalPt, position, &hitObj, &contextObj, flags); + wxRichTextDrawingContext context(& GetBuffer()); + hit = GetBuffer().HitTest(dc, context, logicalPt, position, &hitObj, &contextObj, flags); wxRichTextParagraphLayoutBox* container = wxDynamicCast(contextObj, wxRichTextParagraphLayoutBox); return container; @@ -3390,7 +3399,8 @@ int wxRichTextCtrl::PrepareContextMenu(wxMenu* menu, const wxPoint& pt, bool add if (pt != wxDefaultPosition) { wxPoint logicalPt = GetLogicalPoint(ScreenToClient(pt)); - int hit = GetBuffer().HitTest(dc, logicalPt, position, & hitObj, & contextObj); + wxRichTextDrawingContext context(& GetBuffer()); + int hit = GetBuffer().HitTest(dc, context, logicalPt, position, & hitObj, & contextObj); if (hit == wxRICHTEXT_HITTEST_ON || hit == wxRICHTEXT_HITTEST_BEFORE || hit == wxRICHTEXT_HITTEST_AFTER) { @@ -3678,7 +3688,8 @@ bool wxRichTextCtrl::GetCaretPositionForIndex(long position, wxRect& rect, wxRic if (!container) container = GetFocusObject(); - if (container->FindPosition(dc, position, pt, & height, m_caretAtLineStart)) + wxRichTextDrawingContext context(& GetBuffer()); + if (container->FindPosition(dc, context, position, pt, & height, m_caretAtLineStart)) { // Caret height can't be zero if (height == 0) @@ -3758,9 +3769,10 @@ bool wxRichTextCtrl::LayoutContent(bool onlyVisibleRect) PrepareDC(dc); + wxRichTextDrawingContext context(& GetBuffer()); GetBuffer().Defragment(); GetBuffer().UpdateRanges(); // If items were deleted, ranges need recalculation - GetBuffer().Layout(dc, availableSpace, availableSpace, flags); + GetBuffer().Layout(dc, context, availableSpace, availableSpace, flags); GetBuffer().Invalidate(wxRICHTEXT_NONE); if (!IsFrozen()) diff --git a/src/richtext/richtextprint.cpp b/src/richtext/richtextprint.cpp index b053e75ff6..e15de6c91b 100644 --- a/src/richtext/richtextprint.cpp +++ b/src/richtext/richtextprint.cpp @@ -67,7 +67,8 @@ void wxRichTextPrintout::OnPreparePrinting() { GetRichTextBuffer()->Invalidate(wxRICHTEXT_ALL); - GetRichTextBuffer()->Layout(*GetDC(), rect, rect, wxRICHTEXT_FIXED_WIDTH|wxRICHTEXT_VARIABLE_HEIGHT); + wxRichTextDrawingContext context(GetRichTextBuffer()); + GetRichTextBuffer()->Layout(*GetDC(), context, rect, rect, wxRICHTEXT_FIXED_WIDTH|wxRICHTEXT_VARIABLE_HEIGHT); // Now calculate the page breaks @@ -300,7 +301,8 @@ void wxRichTextPrintout::RenderPage(wxDC *dc, int page) dc->SetClippingRegion(wxRect(textRect.x, textRect.y + yOffset, textRect.width, textRect.height)); - GetRichTextBuffer()->Draw(*dc, rangeToDraw, wxRichTextSelection(), textRect, 0 /* descent */, wxRICHTEXT_DRAW_IGNORE_CACHE|wxRICHTEXT_DRAW_PRINT /* flags */); + wxRichTextDrawingContext context(GetRichTextBuffer()); + GetRichTextBuffer()->Draw(*dc, context, rangeToDraw, wxRichTextSelection(), textRect, 0 /* descent */, wxRICHTEXT_DRAW_IGNORE_CACHE|wxRICHTEXT_DRAW_PRINT /* flags */); dc->DestroyClippingRegion(); -- 2.45.2