The top of the hierarchy is the buffer, a kind of wxRichTextParagraphLayoutBox.
These boxes will allow flexible placement of text boxes on a page, but
- for now there will be a single box representing the document,
- and this box will a wxRichTextParagraphLayoutBox which contains further
- wxRichTextParagraph objects, each of which can include text and images.
+ for now there is a single box representing the document, and this box is
+ a wxRichTextParagraphLayoutBox which contains further wxRichTextParagraph
+ objects, each of which can include text and images.
Each object maintains a range (start and end position) measured
from the start of the main parent box.
a position relative to that text box. For now, we will not be dealing with
embedded objects but it's something to bear in mind for later.
+ Note that internally, a range (5,5) represents a range of one character.
+ In the public wx[Rich]TextCtrl API, this would be passed to e.g. SetSelection
+ as (5,6). A paragraph with one character might have an internal range of (0, 1)
+ since the end of the paragraph takes up one position.
+
Layout
======
in the vertical direction. The implementation of Layout can then
cache the calculated size and position within the parent.
- Note that position and size should be calculated separately, because
- for example inserting a paragraph may result in the following paragraphs
- moving down, but not changing in size.
-
- Need to determine how objects specify their position. Absolute coordinates,
- or relative to last object? May be hard to determine that. So should probably
- be in absolute coordinates, in which case we'll need a Move virtual function
- that allows quick movement of all elements without layout.
-
- Let's work through a simple example of layout. Say we're laying out
- a document with the buffer as the top box, with a wxRichTextParagraphLayoutBox
- inside that that consists of wxRichTextParagraph objects.
-
- We're in a mode whereby changes of window size change the width of the
- page (useful for text editors, as opposed to word processors). The
- window width is 600.
-
- We pass (600, -1) to the top-level Layout (i.e. restrict size in horizontal
- direction only). The wxRichTextBuffer box doesn't currently have
- well-defined layout behaviour so we simply assume it has one child
- that fills its parent (later we can define sizer-like box layout behaviour).
- So it passes the same dimensions to the child, which is a wxRichTextParagraphLayoutBox.
- This then looks at each child in turn (wxRichTextParagraph) and determines
- the size the paragraph will take up, setting the cached size, and
- splitting the paragraph into lines.
-
- When the layout for one paragraph returns, the next paragraph is
- fed the position of the previous, so it can position itself.
-
- Each time Layout is called, the cached list of lines for each paragraph
- is recreated, since it can change for example if the parent object width
- changes.
-
- Reporting size
- ==============
-
- Each object can report its size for a given range. It's important that
- it can report a partial size, so that wrapping can be implemented,
- hit test calculations performed, etc. So GetRangeSize must be implemented
- for each object.
-
*/
/*!
#include "wx/cmdproc.h"
#include "wx/txtstrm.h"
+#if wxUSE_DATAOBJ
+#include "wx/dataobj.h"
+#endif
+
// Experimental dynamic styles to avoid user-specific character styles from being
// overwritten by paragraph styles.
#define wxRICHTEXT_USE_DYNAMIC_STYLES 1
class WXDLLIMPEXP_RICHTEXT wxRichTextObjectList;
class WXDLLIMPEXP_RICHTEXT wxRichTextLine;
class WXDLLIMPEXP_RICHTEXT wxRichTextParagraph;
-class WXDLLIMPEXP_RICHTEXT wxRichTextFragment;
class WXDLLIMPEXP_RICHTEXT wxRichTextFileHandler;
class WXDLLIMPEXP_RICHTEXT wxRichTextStyleSheet;
class WXDLLIMPEXP_RICHTEXT wxTextAttrEx;
#define wxRICHTEXT_FORMATTED 0x01
#define wxRICHTEXT_UNFORMATTED 0x02
+/*!
+ * Flags for SetStyle
+ */
+
+#define wxRICHTEXT_SETSTYLE_NONE 0x00
+
+// Specifies that this operation should be undoable
+#define wxRICHTEXT_SETSTYLE_WITH_UNDO 0x01
+
+// Specifies that the style should not be applied if the
+// combined style at this point is already the style in question.
+#define wxRICHTEXT_SETSTYLE_OPTIMIZE 0x02
+
+// Specifies that the style should only be applied to paragraphs,
+// and not the content. This allows content styling to be
+// preserved independently from that of e.g. a named paragraph style.
+#define wxRICHTEXT_SETSTYLE_PARAGRAPHS_ONLY 0x04
+
+// Specifies that the style should only be applied to characters,
+// and not the paragraph. This allows content styling to be
+// preserved independently from that of e.g. a named paragraph style.
+#define wxRICHTEXT_SETSTYLE_CHARACTERS_ONLY 0x08
+
/*!
* Flags for text insertion
*/
void SetBulletStyle(int style) { m_bulletStyle = style; SetFlags(GetFlags() | wxTEXT_ATTR_BULLET_STYLE); }
void SetBulletNumber(int n) { m_bulletNumber = n; SetFlags(GetFlags() | wxTEXT_ATTR_BULLET_NUMBER); }
void SetBulletSymbol(wxChar symbol) { m_bulletSymbol = symbol; SetFlags(GetFlags() | wxTEXT_ATTR_BULLET_SYMBOL); }
+ void SetBulletFont(const wxString& bulletFont) { m_bulletFont = bulletFont; }
const wxString& GetCharacterStyleName() const { return m_characterStyleName; }
const wxString& GetParagraphStyleName() const { return m_paragraphStyleName; }
int GetBulletStyle() const { return m_bulletStyle; }
int GetBulletNumber() const { return m_bulletNumber; }
wxChar GetBulletSymbol() const { return m_bulletSymbol; }
+ const wxString& GetBulletFont() const { return m_bulletFont; }
bool HasWeight() const { return (GetFlags() & wxTEXT_ATTR_FONT_WEIGHT) != 0; }
bool HasSize() const { return (GetFlags() & wxTEXT_ATTR_FONT_SIZE) != 0; }
int m_bulletStyle;
int m_bulletNumber;
wxChar m_bulletSymbol;
+ wxString m_bulletFont;
// Character style
wxString m_characterStyleName;
void SetBulletStyle(int style) { m_bulletStyle = style; m_flags |= wxTEXT_ATTR_BULLET_STYLE; }
void SetBulletNumber(int n) { m_bulletNumber = n; m_flags |= wxTEXT_ATTR_BULLET_NUMBER; }
void SetBulletSymbol(wxChar symbol) { m_bulletSymbol = symbol; m_flags |= wxTEXT_ATTR_BULLET_NUMBER; }
+ void SetBulletFont(const wxString& bulletFont) { m_bulletFont = bulletFont; }
const wxColour& GetTextColour() const { return m_colText; }
const wxColour& GetBackgroundColour() const { return m_colBack; }
int GetBulletStyle() const { return m_bulletStyle; }
int GetBulletNumber() const { return m_bulletNumber; }
wxChar GetBulletSymbol() const { return m_bulletSymbol; }
+ const wxString& GetBulletFont() const { return m_bulletFont; }
// accessors
bool HasTextColour() const { return m_colText.Ok() && HasFlag(wxTEXT_ATTR_TEXT_COLOUR) ; }
int m_bulletStyle;
int m_bulletNumber;
wxChar m_bulletSymbol;
+ wxString m_bulletFont;
// Character styles
wxColour m_colText,
wxString m_paragraphStyleName;
};
-#define wxTEXT_ATTR_CHARACTER (wxTEXT_ATTR_FONT | wxTEXT_ATTR_BACKGROUND_COLOUR | wxTEXT_ATTR_TEXT_COLOUR)
+#define wxTEXT_ATTR_CHARACTER (wxTEXT_ATTR_FONT | wxTEXT_ATTR_BACKGROUND_COLOUR | wxTEXT_ATTR_TEXT_COLOUR | wxTEXT_ATTR_CHARACTER_STYLE_NAME)
#define wxTEXT_ATTR_PARAGRAPH (wxTEXT_ATTR_ALIGNMENT|wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT|wxTEXT_ATTR_TABS|\
wxTEXT_ATTR_PARA_SPACING_BEFORE|wxTEXT_ATTR_PARA_SPACING_AFTER|wxTEXT_ATTR_LINE_SPACING|\
- wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER|wxTEXT_ATTR_BULLET_SYMBOL)
+ wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER|wxTEXT_ATTR_BULLET_SYMBOL|wxTEXT_ATTR_PARAGRAPH_STYLE_NAME)
#define wxTEXT_ATTR_ALL (wxTEXT_ATTR_CHARACTER|wxTEXT_ATTR_PARAGRAPH)
/// Copy
void Copy(const wxRichTextCompositeObject& obj);
+ /// Assignment
+ void operator= (const wxRichTextCompositeObject& obj) { Copy(obj); }
+
/// Append a child, returning the position
size_t AppendChild(wxRichTextObject* child) ;
// Constructors
wxRichTextParagraphLayoutBox(wxRichTextObject* parent = NULL);
- wxRichTextParagraphLayoutBox(const wxRichTextParagraphLayoutBox& obj):wxRichTextBox() { Init(); Copy(obj); }
+ wxRichTextParagraphLayoutBox(const wxRichTextParagraphLayoutBox& obj): wxRichTextBox() { Init(); Copy(obj); }
// Overrideables
/// Get the associated control.
wxRichTextCtrl* GetRichTextCtrl() const { return m_ctrl; }
+ /// Get/set whether the last paragraph is partial or complete
+ void SetPartialParagraph(bool partialPara) { m_partialParagraph = partialPara; }
+ bool GetPartialParagraph() const { return m_partialParagraph; }
+
// Operations
/// Initialize the object.
virtual bool PositionToXY(long pos, long* x, long* y) const;
/// Set text attributes: character and/or paragraph styles.
- virtual bool SetStyle(const wxRichTextRange& range, const wxRichTextAttr& style, bool withUndo = true);
- virtual bool SetStyle(const wxRichTextRange& range, const wxTextAttrEx& style, bool withUndo = true);
+ virtual bool SetStyle(const wxRichTextRange& range, const wxRichTextAttr& style, int flags = wxRICHTEXT_SETSTYLE_WITH_UNDO);
+ virtual bool SetStyle(const wxRichTextRange& range, const wxTextAttrEx& style, int flags = wxRICHTEXT_SETSTYLE_WITH_UNDO);
/// Get the conbined text attributes for this position.
virtual bool GetStyle(long position, wxTextAttrEx& style);
/// context attributes.
virtual bool DoGetStyle(long position, wxTextAttrEx& style, bool combineStyles = true);
+ /// Get the combined style for a range - if any attribute is different within the range,
+ /// that attribute is not present within the flags
+ virtual bool GetStyleForRange(const wxRichTextRange& range, wxTextAttrEx& style);
+
+ /// Combines 'style' with 'currentStyle' for the purpose of summarising the attributes of a range of
+ /// content.
+ bool CollectStyle(wxTextAttrEx& currentStyle, const wxTextAttrEx& style, long& multipleStyleAttributes);
+
/// Test if this whole range has character attributes of the specified kind. If any
/// of the attributes are different within the range, the test fails. You
/// can use this to implement, for example, bold button updating. style must have
/// Insert fragment into this box at the given position. If partialParagraph is true,
/// it is assumed that the last (or only) paragraph is just a piece of data with no paragraph
/// marker.
- virtual bool InsertFragment(long position, wxRichTextFragment& fragment);
+ virtual bool InsertFragment(long position, wxRichTextParagraphLayoutBox& fragment);
/// Make a copy of the fragment corresponding to the given range, putting it in 'fragment'.
- virtual bool CopyFragment(const wxRichTextRange& range, wxRichTextFragment& fragment);
+ virtual bool CopyFragment(const wxRichTextRange& range, wxRichTextParagraphLayoutBox& fragment);
/// Apply the style sheet to the buffer, for example if the styles have changed.
virtual bool ApplyStyleSheet(wxRichTextStyleSheet* styleSheet);
/// Copy
void Copy(const wxRichTextParagraphLayoutBox& obj);
+ /// Assignment
+ void operator= (const wxRichTextParagraphLayoutBox& obj) { Copy(obj); }
+
/// Calculate ranges
virtual void UpdateRanges() { long end; CalculateRange(0, end); }
wxTextAttrEx m_defaultAttributes;
/// The invalidated range that will need full layout
- wxRichTextRange m_invalidRange;
-};
-
-/*!
- * wxRichTextFragment class declaration
- * This is a lind of paragraph layout box used for storing
- * paragraphs for Undo/Redo, for example.
- */
-
-class WXDLLIMPEXP_RICHTEXT wxRichTextFragment: public wxRichTextParagraphLayoutBox
-{
- DECLARE_DYNAMIC_CLASS(wxRichTextFragment)
-public:
-// Constructors
-
- wxRichTextFragment() { Init(); }
- wxRichTextFragment(const wxRichTextFragment& obj):wxRichTextParagraphLayoutBox() { Init(); Copy(obj); }
-
-// Accessors
-
- /// Get/set whether the last paragraph is partial or complete
- void SetPartialParagraph(bool partialPara) { m_partialParagraph = partialPara; }
- bool GetPartialParagraph() const { return m_partialParagraph; }
-
-// Overrideables
-
-// Operations
-
- /// Initialise
- void Init();
-
- /// Copy
- void Copy(const wxRichTextFragment& obj);
-
- /// Clone
- virtual wxRichTextObject* Clone() const { return new wxRichTextFragment(*this); }
-
-protected:
+ wxRichTextRange m_invalidRange;
// Is the last paragraph partial or complete?
- bool m_partialParagraph;
+ bool m_partialParagraph;
};
/*!
wxRichTextParagraph(wxRichTextObject* parent = NULL, wxTextAttrEx* style = NULL);
wxRichTextParagraph(const wxString& text, wxRichTextObject* parent = NULL, wxTextAttrEx* style = NULL);
virtual ~wxRichTextParagraph();
- wxRichTextParagraph(const wxRichTextParagraph& obj):wxRichTextBox() { Copy(obj); }
+ wxRichTextParagraph(const wxRichTextParagraph& obj): wxRichTextBox() { Copy(obj); }
// Overrideables
/// Get combined attributes of the base style, paragraph style and character style. We use this to dynamically
/// retrieve the actual style.
- wxTextAttrEx GetCombinedAttributes(const wxTextAttr& contentStyle) const;
+ wxTextAttrEx GetCombinedAttributes(const wxTextAttrEx& contentStyle) const;
/// Get combined attributes of the base style and paragraph style.
wxTextAttrEx GetCombinedAttributes() const;
// Constructors
wxRichTextPlainText(const wxString& text = wxEmptyString, wxRichTextObject* parent = NULL, wxTextAttrEx* style = NULL);
- wxRichTextPlainText(const wxRichTextPlainText& obj):wxRichTextObject() { Copy(obj); }
+ wxRichTextPlainText(const wxRichTextPlainText& obj): wxRichTextObject() { Copy(obj); }
// Overrideables
void SetDataSize(size_t size) { m_dataSize = size; }
void SetImageType(int imageType) { m_imageType = imageType; }
- bool Ok() const { return GetData() != NULL; }
+ bool Ok() const { return IsOk(); }
+ bool IsOk() const { return GetData() != NULL; }
/// Implementation
public:
// Constructors
- wxRichTextImage(wxRichTextObject* parent = NULL):wxRichTextObject(parent) { }
+ wxRichTextImage(wxRichTextObject* parent = NULL): wxRichTextObject(parent) { }
wxRichTextImage(const wxImage& image, wxRichTextObject* parent = NULL);
wxRichTextImage(const wxRichTextImageBlock& imageBlock, wxRichTextObject* parent = NULL);
- wxRichTextImage(const wxRichTextImage& obj):wxRichTextObject() { Copy(obj); }
+ wxRichTextImage(const wxRichTextImage& obj): wxRichTextObject() { Copy(obj); }
// Overrideables
// Constructors
wxRichTextBuffer() { Init(); }
- wxRichTextBuffer(const wxRichTextBuffer& obj):wxRichTextParagraphLayoutBox() { Init(); Copy(obj); }
+ wxRichTextBuffer(const wxRichTextBuffer& obj): wxRichTextParagraphLayoutBox() { Init(); Copy(obj); }
virtual ~wxRichTextBuffer() ;
// Accessors
virtual bool SaveFile(wxOutputStream& stream, int type = wxRICHTEXT_TYPE_ANY);
/// Convenience function to add a paragraph of text
- virtual wxRichTextRange AddParagraph(const wxString& text) { Modify(); return wxRichTextParagraphLayoutBox::AddParagraph(text); }
+ virtual wxRichTextRange AddParagraph(const wxString& text, wxTextAttrEx* paraStyle = NULL) { Modify(); return wxRichTextParagraphLayoutBox::AddParagraph(text, paraStyle); }
/// Begin collapsing undo/redo commands. Note that this may not work properly
/// if combining commands that delete or insert content, changing ranges for
// Implementation
/// Copy
- void Copy(const wxRichTextBuffer& obj) { wxRichTextBox::Copy(obj); }
+ void Copy(const wxRichTextBuffer& obj);
/// Clone
virtual wxRichTextObject* Clone() const { return new wxRichTextBuffer(*this); }
+ /// Submit command to insert paragraphs
+ bool InsertParagraphsWithUndo(long pos, const wxRichTextParagraphLayoutBox& paragraphs, wxRichTextCtrl* ctrl, int flags = 0);
+
/// Submit command to insert the given text
bool InsertTextWithUndo(long pos, const wxString& text, wxRichTextCtrl* ctrl, int flags = 0);
void UpdateAppearance(long caretPosition, bool sendUpdateEvent = false);
/// Replace the buffer paragraphs with the given fragment.
- void ApplyParagraphs(const wxRichTextFragment& fragment);
+ void ApplyParagraphs(const wxRichTextParagraphLayoutBox& fragment);
/// Get the fragments
- wxRichTextFragment& GetNewParagraphs() { return m_newParagraphs; }
- wxRichTextFragment& GetOldParagraphs() { return m_oldParagraphs; }
+ wxRichTextParagraphLayoutBox& GetNewParagraphs() { return m_newParagraphs; }
+ wxRichTextParagraphLayoutBox& GetOldParagraphs() { return m_oldParagraphs; }
/// Set/get the position used for e.g. insertion
void SetPosition(long pos) { m_position = pos; }
wxRichTextCtrl* m_ctrl;
// Stores the new paragraphs
- wxRichTextFragment m_newParagraphs;
+ wxRichTextParagraphLayoutBox m_newParagraphs;
// Stores the old paragraphs
- wxRichTextFragment m_oldParagraphs;
+ wxRichTextParagraphLayoutBox m_oldParagraphs;
// The affected range
wxRichTextRange m_range;
};
+#if wxUSE_DATAOBJ
+
+/*!
+ * The data object for a wxRichTextBuffer
+ */
+
+class wxRichTextBufferDataObject: public wxDataObjectSimple
+{
+public:
+ // ctor doesn't copy the pointer, so it shouldn't go away while this object
+ // is alive
+ wxRichTextBufferDataObject(wxRichTextBuffer* richTextBuffer = (wxRichTextBuffer*) NULL);
+ virtual ~wxRichTextBufferDataObject();
+
+ // after a call to this function, the buffer is owned by the caller and it
+ // is responsible for deleting it
+ wxRichTextBuffer* GetRichTextBuffer();
+
+ // Returns the id for the new data format
+ static const wxChar* GetRichTextBufferFormatId() { return ms_richTextBufferFormatId; }
+
+ // base class pure virtuals
+
+ virtual wxDataFormat GetPreferredFormat(Direction dir) const;
+ virtual size_t GetDataSize() const;
+ virtual bool GetDataHere(void *pBuf) const;
+ virtual bool SetData(size_t len, const void *buf);
+
+ // prevent warnings
+
+ virtual size_t GetDataSize(const wxDataFormat&) const { return GetDataSize(); }
+ virtual bool GetDataHere(const wxDataFormat&, void *buf) const { return GetDataHere(buf); }
+ virtual bool SetData(const wxDataFormat&, size_t len, const void *buf) { return SetData(len, buf); }
+
+private:
+ wxDataFormat m_formatRichTextBuffer; // our custom format
+ wxRichTextBuffer* m_richTextBuffer; // our data
+ static const wxChar* ms_richTextBufferFormatId; // our format id
+};
+
+#endif
+
/*!
* Utilities
*
/// Apply one style to another
bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxTextAttrEx& style);
bool wxRichTextApplyStyle(wxRichTextAttr& destStyle, const wxTextAttrEx& style);
-bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style);
+bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style, wxRichTextAttr* compareWith = NULL);
+
+/// Compare tabs
+bool wxRichTextTabsEq(const wxArrayInt& tabs1, const wxArrayInt& tabs2);
+
+/// Set the font without changing the font attributes
+void wxSetFontPreservingStyles(wxTextAttr& attr, const wxFont& font);
+
+/// Convert a decimal to Roman numerals
+wxString wxRichTextDecimalToRoman(long n);
#endif
// wxUSE_RICHTEXT
#endif
// _WX_RICHTEXTBUFFER_H_
+