From fe5aa22c174da89809b6c5d27e60300df0b879ac Mon Sep 17 00:00:00 2001 From: Julian Smart Date: Fri, 29 Sep 2006 08:53:23 +0000 Subject: [PATCH] Fixed bugs in, and added operators and copy constructors to, style sheet classes. Now merges base, paragraph and content styles dynamically on display or layout so that we can distinguish between them. This means appling a paragraph style that has character formatting doesn't wipe out the original content formatting. The old-style static method can be enabled by setting wxRICHTEXT_USE_DYNAMIC_STYLES to 0 in richtextbuffer.h. The default style is initially empty, so that adding text reflects the base and paragraph styles. Setting the default style doesn't merge with the previous setting, but BeginStyle does. Adding new paragraphs is now sensitive to the previous paragraph's style and also whether its style has a next-paragraph style indication. Added wxRichTextCtrl::ApplyStyleSheet which reapplies styles to paragraphs with named styles. Added style application command to sample to demonstrate how styles can be changed and reapplied without affecting content character formatting. Fixed some range bugs in UI feedback and clipboard copying and pasting. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41501 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/richtext/richtextbuffer.h | 55 ++- include/wx/richtext/richtextctrl.h | 14 +- include/wx/richtext/richtextstyles.h | 29 +- samples/richtext/richtext.cpp | 75 +++- src/richtext/richtextbuffer.cpp | 547 ++++++++++++++++++++++----- src/richtext/richtextctrl.cpp | 83 +++- src/richtext/richtextstyles.cpp | 91 ++++- 7 files changed, 765 insertions(+), 129 deletions(-) diff --git a/include/wx/richtext/richtextbuffer.h b/include/wx/richtext/richtextbuffer.h index fa9fd77144..45eb308cff 100644 --- a/include/wx/richtext/richtextbuffer.h +++ b/include/wx/richtext/richtextbuffer.h @@ -102,6 +102,10 @@ #include "wx/cmdproc.h" #include "wx/txtstrm.h" +// Experimental dynamic styles to avoid user-specific character styles from being +// overwritten by paragraph styles. +#define wxRICHTEXT_USE_DYNAMIC_STYLES 1 + /*! * File types */ @@ -161,6 +165,13 @@ class WXDLLIMPEXP_RICHTEXT wxTextAttrEx; #define wxRICHTEXT_FORMATTED 0x01 #define wxRICHTEXT_UNFORMATTED 0x02 +/*! + * Flags for text insertion + */ + +#define wxRICHTEXT_INSERT_NONE 0x00 +#define wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE 0x01 + /*! * Extra formatting flags not in wxTextAttr */ @@ -378,6 +389,9 @@ public: // Assignment from a wxTextAttrEx object. void operator= (const wxTextAttrEx& attr); + // Equality test + bool operator== (const wxRichTextAttr& attr) const; + // Making a wxTextAttrEx object. operator wxTextAttrEx () const ; @@ -853,13 +867,13 @@ public: virtual void Reset(); /// Convenience function to add a paragraph of text - virtual wxRichTextRange AddParagraph(const wxString& text); + virtual wxRichTextRange AddParagraph(const wxString& text, wxTextAttrEx* paraStyle = NULL); /// Convenience function to add an image - virtual wxRichTextRange AddImage(const wxImage& image); + virtual wxRichTextRange AddImage(const wxImage& image, wxTextAttrEx* paraStyle = NULL); /// Adds multiple paragraphs, based on newlines. - virtual wxRichTextRange AddParagraphs(const wxString& text); + virtual wxRichTextRange AddParagraphs(const wxString& text, wxTextAttrEx* paraStyle = NULL); /// Get the line at the given position. If caretPosition is true, the position is /// a caret position, which is normally a smaller number. @@ -916,10 +930,18 @@ public: virtual bool SetStyle(const wxRichTextRange& range, const wxRichTextAttr& style, bool withUndo = true); virtual bool SetStyle(const wxRichTextRange& range, const wxTextAttrEx& style, bool withUndo = true); - /// Get the text attributes for this position. + /// Get the conbined text attributes for this position. virtual bool GetStyle(long position, wxTextAttrEx& style); virtual bool GetStyle(long position, wxRichTextAttr& style); + /// Get the content (uncombined) attributes for this position. + virtual bool GetUncombinedStyle(long position, wxTextAttrEx& style); + virtual bool GetUncombinedStyle(long position, wxRichTextAttr& style); + + /// Implementation helper for GetStyle. If combineStyles is true, combine base, paragraph and + /// context attributes. + virtual bool DoGetStyle(long position, wxTextAttrEx& style, bool combineStyles = true); + /// 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 @@ -945,6 +967,9 @@ public: /// Make a copy of the fragment corresponding to the given range, putting it in 'fragment'. virtual bool CopyFragment(const wxRichTextRange& range, wxRichTextFragment& 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); @@ -1161,7 +1186,7 @@ public: // Implementation /// Apply paragraph styles such as centering to the wrapped lines - virtual void ApplyParagraphStyle(const wxRect& rect); + virtual void ApplyParagraphStyle(const wxTextAttrEx& attr, const wxRect& rect); /// Insert text at the given position virtual bool InsertText(long pos, const wxString& text); @@ -1196,6 +1221,13 @@ public: /// Clear remaining unused line objects, if any bool ClearUnusedLines(int lineCount); + /// 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; + + /// Get combined attributes of the base style and paragraph style. + wxTextAttrEx GetCombinedAttributes() const; + protected: /// The lines that make up the wrapped paragraph wxRichTextLineList m_cachedLines; @@ -1269,7 +1301,7 @@ public: /// Clone virtual wxRichTextObject* Clone() const { return new wxRichTextPlainText(*this); } private: - bool DrawTabbedString(wxDC& dc,const wxRect& rect,wxString& str, wxCoord& x, wxCoord& y, bool selected); + bool DrawTabbedString(wxDC& dc, const wxTextAttrEx& attr, const wxRect& rect, wxString& str, wxCoord& x, wxCoord& y, bool selected); protected: wxString m_text; @@ -1623,13 +1655,13 @@ public: virtual wxRichTextObject* Clone() const { return new wxRichTextBuffer(*this); } /// Submit command to insert the given text - bool InsertTextWithUndo(long pos, const wxString& text, wxRichTextCtrl* ctrl); + bool InsertTextWithUndo(long pos, const wxString& text, wxRichTextCtrl* ctrl, int flags = 0); /// Submit command to insert a newline - bool InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl); + bool InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl, int flags = 0); /// Submit command to insert the given image - bool InsertImageWithUndo(long pos, const wxRichTextImageBlock& imageBlock, wxRichTextCtrl* ctrl); + bool InsertImageWithUndo(long pos, const wxRichTextImageBlock& imageBlock, wxRichTextCtrl* ctrl, int flags = 0); /// Submit command to delete this range bool DeleteRangeWithUndo(const wxRichTextRange& range, long initialCaretPosition, long newCaretPositon, wxRichTextCtrl* ctrl); @@ -1638,6 +1670,11 @@ public: void Modify(bool modify = true) { m_modified = modify; } bool IsModified() const { return m_modified; } + /// Get the style that is appropriate for a new paragraph at this position. + /// If the previous paragraph has a paragraph style name, look up the next-paragraph + /// style. + wxRichTextAttr GetStyleForNewParagraph(long pos, bool caretPosition = false) const; + /// Dumps contents of buffer for debugging purposes virtual void Dump(); virtual void Dump(wxTextOutputStream& stream) { wxRichTextParagraphLayoutBox::Dump(stream); } diff --git a/include/wx/richtext/richtextctrl.h b/include/wx/richtext/richtextctrl.h index 9cad286cde..bf1e62bafd 100644 --- a/include/wx/richtext/richtextctrl.h +++ b/include/wx/richtext/richtextctrl.h @@ -188,6 +188,12 @@ public: virtual bool GetStyle(long position, wxTextAttr& style); virtual bool GetStyle(long position, wxTextAttrEx& style); virtual bool GetStyle(long position, wxRichTextAttr& style); + + /// Get the content (uncombined) attributes for this position. + virtual bool GetUncombinedStyle(long position, wxTextAttr& style); + virtual bool GetUncombinedStyle(long position, wxTextAttrEx& style); + virtual bool GetUncombinedStyle(long position, wxRichTextAttr& style); + virtual bool SetDefaultStyle(const wxTextAttrEx& style); virtual bool SetDefaultStyle(const wxTextAttr& style); @@ -530,6 +536,9 @@ public: void SetStyleSheet(wxRichTextStyleSheet* styleSheet) { GetBuffer().SetStyleSheet(styleSheet); } wxRichTextStyleSheet* GetStyleSheet() const { return GetBuffer().GetStyleSheet(); } + /// Apply the style sheet to the buffer, for example if the styles have changed. + bool ApplyStyleSheet(wxRichTextStyleSheet* styleSheet = NULL); + // Command handlers void Command(wxCommandEvent& event); @@ -595,8 +604,6 @@ public: /// Scrolling void OnScroll(wxScrollWinEvent& event); -// Implementation - /// Set font, and also default attributes virtual bool SetFont(const wxFont& font); @@ -717,6 +724,8 @@ public: SetCaretPositionForDefaultStyle(GetCaretPosition()); } +// Implementation + #if wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE WX_FORWARD_TO_SCROLL_HELPER() #endif @@ -845,4 +854,3 @@ typedef void (wxEvtHandler::*wxRichTextEventFunction)(wxRichTextEvent&); #endif // _WX_RICHTEXTCTRL_H_ - diff --git a/include/wx/richtext/richtextstyles.h b/include/wx/richtext/richtextstyles.h index 997d3e9744..89672946ed 100644 --- a/include/wx/richtext/richtextstyles.h +++ b/include/wx/richtext/richtextstyles.h @@ -47,10 +47,15 @@ public: // Constructors + wxRichTextStyleDefinition(const wxRichTextStyleDefinition& def) { Copy(def); } wxRichTextStyleDefinition(const wxString& name = wxEmptyString) { Init(); m_name = name; } virtual ~wxRichTextStyleDefinition() {} void Init() {} + void Copy(const wxRichTextStyleDefinition& def); + bool Eq(const wxRichTextStyleDefinition& def) const; + void operator =(const wxRichTextStyleDefinition& def) { Copy(def); } + bool operator ==(const wxRichTextStyleDefinition& def) const { return Eq(def); } /// The name of the style. void SetName(const wxString& name) { m_name = name; } @@ -82,6 +87,7 @@ public: // Constructors + wxRichTextCharacterStyleDefinition(const wxRichTextCharacterStyleDefinition& def): wxRichTextStyleDefinition(def) {} wxRichTextCharacterStyleDefinition(const wxString& name = wxEmptyString): wxRichTextStyleDefinition(name) {} virtual ~wxRichTextCharacterStyleDefinition() {} @@ -100,6 +106,7 @@ public: // Constructors + wxRichTextParagraphStyleDefinition(const wxRichTextParagraphStyleDefinition& def): wxRichTextStyleDefinition(def) { m_nextStyle = def.m_nextStyle; } wxRichTextParagraphStyleDefinition(const wxString& name = wxEmptyString): wxRichTextStyleDefinition(name) {} virtual ~wxRichTextParagraphStyleDefinition() {} @@ -108,6 +115,10 @@ public: void SetNextStyle(const wxString& name) { m_nextStyle = name; } const wxString& GetNextStyle() const { return m_nextStyle; } + void Copy(const wxRichTextParagraphStyleDefinition& def); + void operator =(const wxRichTextParagraphStyleDefinition& def) { Copy(def); } + bool operator ==(const wxRichTextParagraphStyleDefinition& def) const; + protected: /// The next style to use when adding a paragraph after this style. @@ -124,29 +135,39 @@ class WXDLLIMPEXP_RICHTEXT wxRichTextStyleSheet: public wxObject public: /// Constructors + wxRichTextStyleSheet(const wxRichTextStyleSheet& sheet) { Copy(sheet); } wxRichTextStyleSheet() { Init(); } virtual ~wxRichTextStyleSheet() { DeleteStyles(); } /// Initialisation void Init(); + /// Copy + void Copy(const wxRichTextStyleSheet& sheet); + + /// Assignment + void operator=(const wxRichTextStyleSheet& sheet) { Copy(sheet); } + + /// Equality + bool operator==(const wxRichTextStyleSheet& sheet) const; + /// Add a definition to the character style list - bool AddCharacterStyle(wxRichTextCharacterStyleDefinition* def) { return AddStyle(m_characterStyleDefinitions, def); } + bool AddCharacterStyle(wxRichTextCharacterStyleDefinition* def); /// Add a definition to the paragraph style list - bool AddParagraphStyle(wxRichTextParagraphStyleDefinition* def) { return AddStyle(m_paragraphStyleDefinitions, def); } + bool AddParagraphStyle(wxRichTextParagraphStyleDefinition* def); /// Remove a character style bool RemoveCharacterStyle(wxRichTextStyleDefinition* def, bool deleteStyle = false) { return RemoveStyle(m_characterStyleDefinitions, def, deleteStyle); } /// Remove a paragraph style - bool RemoveParagraphStyle(wxRichTextStyleDefinition* def, bool deleteStyle = false) { return RemoveStyle(m_characterStyleDefinitions, def, deleteStyle); } + bool RemoveParagraphStyle(wxRichTextStyleDefinition* def, bool deleteStyle = false) { return RemoveStyle(m_paragraphStyleDefinitions, def, deleteStyle); } /// Find a character definition by name wxRichTextCharacterStyleDefinition* FindCharacterStyle(const wxString& name) const { return (wxRichTextCharacterStyleDefinition*) FindStyle(m_characterStyleDefinitions, name); } /// Find a paragraph definition by name - wxRichTextParagraphStyleDefinition* FindParagraphStyle(const wxString& name) const { return (wxRichTextParagraphStyleDefinition*) FindStyle(m_characterStyleDefinitions, name); } + wxRichTextParagraphStyleDefinition* FindParagraphStyle(const wxString& name) const { return (wxRichTextParagraphStyleDefinition*) FindStyle(m_paragraphStyleDefinitions, name); } /// Return the number of character styes. size_t GetCharacterStyleCount() const { return m_characterStyleDefinitions.GetCount(); } diff --git a/samples/richtext/richtext.cpp b/samples/richtext/richtext.cpp index e0a9968d1e..152b07f68b 100644 --- a/samples/richtext/richtext.cpp +++ b/samples/richtext/richtext.cpp @@ -139,6 +139,8 @@ public: void OnViewHTML(wxCommandEvent& event); + void OnSwitchStyleSheets(wxCommandEvent& event); + // Forward command events to the current rich text control, if any bool ProcessEvent(wxEvent& event); @@ -179,7 +181,12 @@ enum ID_FORMAT_LINE_SPACING_DOUBLE, ID_FORMAT_LINE_SPACING_SINGLE, - ID_VIEW_HTML + ID_VIEW_HTML, + ID_SWITCH_STYLE_SHEETS, + + ID_RICHTEXT_CTRL, + ID_RICHTEXT_STYLE_LIST, + ID_RICHTEXT_STYLE_COMBO }; // ---------------------------------------------------------------------------- @@ -225,6 +232,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(ID_FORMAT_PARAGRAPH_SPACING_LESS, MyFrame::OnParagraphSpacingLess) EVT_MENU(ID_VIEW_HTML, MyFrame::OnViewHTML) + EVT_MENU(ID_SWITCH_STYLE_SHEETS, MyFrame::OnSwitchStyleSheets) END_EVENT_TABLE() // Create a new application object: this macro will allow wxWidgets to create @@ -442,6 +450,8 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos, formatMenu->Append(ID_FORMAT_LINE_SPACING_DOUBLE, _("Double Line Spacing")); formatMenu->AppendSeparator(); formatMenu->Append(ID_FORMAT_FONT, _("&Font...")); + formatMenu->AppendSeparator(); + formatMenu->Append(ID_SWITCH_STYLE_SHEETS, _("&Switch Style Sheets")); // now append the freshly created menu to the menu bar... wxMenuBar *menuBar = new wxMenuBar(); @@ -490,7 +500,7 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos, toolBar->AddSeparator(); toolBar->AddTool(ID_FORMAT_FONT, wxBitmap(font_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Font")); - wxRichTextStyleComboCtrl* combo = new wxRichTextStyleComboCtrl(toolBar, wxID_ANY, wxDefaultPosition, wxSize(200, -1)); + wxRichTextStyleComboCtrl* combo = new wxRichTextStyleComboCtrl(toolBar, ID_RICHTEXT_STYLE_COMBO, wxDefaultPosition, wxSize(200, -1)); toolBar->AddControl(combo); toolBar->Realize(); @@ -501,16 +511,18 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos, wxFont boldFont = wxFont(12, wxROMAN, wxNORMAL, wxBOLD); wxFont italicFont = wxFont(12, wxROMAN, wxITALIC, wxNORMAL); - m_richTextCtrl = new wxRichTextCtrl(splitter, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(200, 200), wxVSCROLL|wxHSCROLL|wxNO_BORDER|wxWANTS_CHARS); + m_richTextCtrl = new wxRichTextCtrl(splitter, ID_RICHTEXT_CTRL, wxEmptyString, wxDefaultPosition, wxSize(200, 200), wxVSCROLL|wxHSCROLL|wxNO_BORDER|wxWANTS_CHARS); wxFont font(12, wxROMAN, wxNORMAL, wxNORMAL); m_richTextCtrl->SetFont(font); + m_richTextCtrl->SetStyleSheet(wxGetApp().GetStyleSheet()); + combo->SetStyleSheet(wxGetApp().GetStyleSheet()); combo->SetRichTextCtrl(m_richTextCtrl); combo->UpdateStyles(); - wxRichTextStyleListBox* styleListBox = new wxRichTextStyleListBox(splitter, wxID_ANY); + wxRichTextStyleListBox* styleListBox = new wxRichTextStyleListBox(splitter, ID_RICHTEXT_STYLE_LIST); wxSize display = wxGetDisplaySize(); if ( is_pda && ( display.GetWidth() < display.GetHeight() ) ) @@ -1073,3 +1085,58 @@ void MyFrame::OnViewHTML(wxCommandEvent& WXUNUSED(event)) dialog.ShowModal(); } + +// Demonstrates how you can change the style sheets and have the changes +// reflected in the control content without wiping out character formatting. + +void MyFrame::OnSwitchStyleSheets(wxCommandEvent& WXUNUSED(event)) +{ + static wxRichTextStyleSheet* gs_AlternateStyleSheet = NULL; + + wxRichTextCtrl* ctrl = (wxRichTextCtrl*) FindWindow(ID_RICHTEXT_CTRL); + wxRichTextStyleListBox* styleList = (wxRichTextStyleListBox*) FindWindow(ID_RICHTEXT_STYLE_LIST); + wxRichTextStyleComboCtrl* styleCombo = (wxRichTextStyleComboCtrl*) FindWindow(ID_RICHTEXT_STYLE_COMBO); + + wxRichTextStyleSheet* sheet = ctrl->GetStyleSheet(); + + // One-time creation of an alternate style sheet + if (!gs_AlternateStyleSheet) + { + gs_AlternateStyleSheet = new wxRichTextStyleSheet(*sheet); + + // Make some modifications + for (int i = 0; i < (int) gs_AlternateStyleSheet->GetParagraphStyleCount(); i++) + { + wxRichTextParagraphStyleDefinition* def = gs_AlternateStyleSheet->GetParagraphStyle(i); + + if (def->GetStyle().HasTextColour()) + def->GetStyle().SetTextColour(*wxBLUE); + + if (def->GetStyle().HasAlignment()) + { + if (def->GetStyle().GetAlignment() == wxTEXT_ALIGNMENT_CENTRE) + def->GetStyle().SetAlignment(wxTEXT_ALIGNMENT_RIGHT); + else if (def->GetStyle().GetAlignment() == wxTEXT_ALIGNMENT_LEFT) + def->GetStyle().SetAlignment(wxTEXT_ALIGNMENT_CENTRE); + } + if (def->GetStyle().HasLeftIndent()) + { + def->GetStyle().SetLeftIndent(def->GetStyle().GetLeftIndent() * 2); + } + } + } + + // Switch sheets + wxRichTextStyleSheet* tmp = gs_AlternateStyleSheet; + gs_AlternateStyleSheet = sheet; + sheet = tmp; + + ctrl->SetStyleSheet(sheet); + ctrl->ApplyStyleSheet(sheet); // Makes the control reflect the new style definitions + + styleList->SetStyleSheet(sheet); + styleList->UpdateStyles(); + + styleCombo->SetStyleSheet(sheet); + styleCombo->UpdateStyles(); +} diff --git a/src/richtext/richtextbuffer.cpp b/src/richtext/richtextbuffer.cpp index bc16bc9efd..ce8a05534d 100644 --- a/src/richtext/richtextbuffer.cpp +++ b/src/richtext/richtextbuffer.cpp @@ -81,11 +81,12 @@ void wxRichTextObject::Copy(const wxRichTextObject& obj) m_range = obj.m_range; m_attributes = obj.m_attributes; m_descent = obj.m_descent; - +/* if (!m_attributes.GetFont().Ok()) wxLogDebug(wxT("No font!")); if (!obj.m_attributes.GetFont().Ok()) wxLogDebug(wxT("Parent has no font!")); +*/ } void wxRichTextObject::SetMargins(int margin) @@ -221,7 +222,9 @@ void wxRichTextCompositeObject::Copy(const wxRichTextCompositeObject& obj) while (node) { wxRichTextObject* child = node->GetData(); - m_children.Append(child->Clone()); + wxRichTextObject* newChild = child->Clone(); + newChild->SetParent(this); + m_children.Append(newChild); node = node->GetNext(); } @@ -869,16 +872,23 @@ wxSize wxRichTextParagraphLayoutBox::GetLineSizeAtPosition(long pos, bool caretP /// Convenience function to add a paragraph of text -wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraph(const wxString& text) +wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraph(const wxString& text, wxTextAttrEx* paraStyle) { +#if wxRICHTEXT_USE_DYNAMIC_STYLES + // Don't use the base style, just the default style, and the base style will + // be combined at display time + wxTextAttrEx style(GetDefaultStyle()); +#else wxTextAttrEx style(GetAttributes()); // Apply default style. If the style has no attributes set, // then the attributes will remain the 'basic style' (i.e. the // layout box's style). wxRichTextApplyStyle(style, GetDefaultStyle()); - +#endif wxRichTextParagraph* para = new wxRichTextParagraph(text, this, & style); + if (paraStyle) + para->SetAttributes(*paraStyle); AppendChild(para); @@ -889,9 +899,15 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraph(const wxString& text) } /// Adds multiple paragraphs, based on newlines. -wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraphs(const wxString& text) +wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraphs(const wxString& text, wxTextAttrEx* paraStyle) { +#if wxRICHTEXT_USE_DYNAMIC_STYLES + // Don't use the base style, just the default style, and the base style will + // be combined at display time + wxTextAttrEx style(GetDefaultStyle()); +#else wxTextAttrEx style(GetAttributes()); + //wxLogDebug("Initial style = %s", style.GetFont().GetFaceName()); //wxLogDebug("Initial size = %d", style.GetFont().GetPointSize()); @@ -902,6 +918,7 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraphs(const wxString& text //wxLogDebug("Style after applying default style = %s", style.GetFont().GetFaceName()); //wxLogDebug("Size after applying default style = %d", style.GetFont().GetPointSize()); +#endif wxRichTextParagraph* firstPara = NULL; wxRichTextParagraph* lastPara = NULL; @@ -916,6 +933,8 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraphs(const wxString& text if (ch == wxT('\n') || ch == wxT('\r')) { wxRichTextParagraph* para = new wxRichTextParagraph(line, this, & style); + if (paraStyle) + para->SetAttributes(*paraStyle); AppendChild(para); if (!firstPara) @@ -931,6 +950,9 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraphs(const wxString& text if (!line.empty()) { lastPara = new wxRichTextParagraph(line, this, & style); + if (paraStyle) + lastPara->SetAttributes(*paraStyle); + //wxLogDebug("Para Face = %s", lastPara->GetAttributes().GetFont().GetFaceName()); AppendChild(lastPara); } @@ -952,19 +974,28 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraphs(const wxString& text } /// Convenience function to add an image -wxRichTextRange wxRichTextParagraphLayoutBox::AddImage(const wxImage& image) +wxRichTextRange wxRichTextParagraphLayoutBox::AddImage(const wxImage& image, wxTextAttrEx* paraStyle) { +#if wxRICHTEXT_USE_DYNAMIC_STYLES + // Don't use the base style, just the default style, and the base style will + // be combined at display time + wxTextAttrEx style(GetDefaultStyle()); +#else wxTextAttrEx style(GetAttributes()); // Apply default style. If the style has no attributes set, // then the attributes will remain the 'basic style' (i.e. the // layout box's style). wxRichTextApplyStyle(style, GetDefaultStyle()); +#endif wxRichTextParagraph* para = new wxRichTextParagraph(this, & style); AppendChild(para); para->AppendChild(new wxRichTextImage(image, this)); + if (paraStyle) + para->SetAttributes(*paraStyle); + UpdateRanges(); SetDirty(true); @@ -1112,7 +1143,9 @@ bool wxRichTextParagraphLayoutBox::InsertFragment(long position, wxRichTextFragm if (finalPara->GetChildCount() == 0) { wxRichTextPlainText* text = new wxRichTextPlainText(wxEmptyString); +#if !wxRICHTEXT_USE_DYNAMIC_STYLES text->SetAttributes(finalPara->GetAttributes()); +#endif finalPara->AppendChild(text); } @@ -1387,8 +1420,8 @@ wxString wxRichTextParagraphLayoutBox::GetTextForRange(const wxRichTextRange& ra wxRichTextObject* child = node->GetData(); if (!child->GetRange().IsOutside(range)) { - if (lineCount > 0) - text += wxT("\n"); +// if (lineCount > 0) +// text += wxT("\n"); wxRichTextRange childRange = range; childRange.LimitTo(child->GetRange()); @@ -1396,6 +1429,9 @@ wxString wxRichTextParagraphLayoutBox::GetTextForRange(const wxRichTextRange& ra text += childText; + if (childRange.GetEnd() == child->GetRange().GetEnd()) + text += wxT("\n"); + lineCount ++; } node = node->GetNext(); @@ -1557,7 +1593,15 @@ bool wxRichTextParagraphLayoutBox::SetStyle(const wxRichTextRange& range, const if (paragraphStyle) wxRichTextApplyStyle(newPara->GetAttributes(), style); +#if wxRICHTEXT_USE_DYNAMIC_STYLES + // If applying paragraph styles dynamically, don't change the text objects' attributes + // since they will computed as needed. Only apply the character styling if it's _only_ + // character styling. This policy is subject to change and might be put under user control. + + if (!paragraphStyle && characterStyle && range.GetStart() != newPara->GetRange().GetEnd()) +#else if (characterStyle && range.GetStart() != newPara->GetRange().GetEnd()) +#endif { wxRichTextRange childRange(range); childRange.LimitTo(newPara->GetRange()); @@ -1635,44 +1679,102 @@ bool wxRichTextParagraphLayoutBox::SetStyle(const wxRichTextRange& range, const /// Get the text attributes for this position. bool wxRichTextParagraphLayoutBox::GetStyle(long position, wxTextAttrEx& style) { - wxRichTextObject* obj wxDUMMY_INITIALIZE(NULL); - - if (style.IsParagraphStyle()) - obj = GetParagraphAtPosition(position); - else - obj = GetLeafObjectAtPosition(position); - - if (obj) - { - style = obj->GetAttributes(); - return true; - } - else - return false; + return DoGetStyle(position, style, true); } /// Get the text attributes for this position. bool wxRichTextParagraphLayoutBox::GetStyle(long position, wxRichTextAttr& style) { - wxRichTextObject* obj wxDUMMY_INITIALIZE(NULL); - - if (style.IsParagraphStyle()) - obj = GetParagraphAtPosition(position); - else - obj = GetLeafObjectAtPosition(position); - - if (obj) + wxTextAttrEx textAttrEx(style); + if (GetStyle(position, textAttrEx)) { - style = obj->GetAttributes(); + style = textAttrEx; return true; } else return false; } +/// Get the content (uncombined) attributes for this position. +bool wxRichTextParagraphLayoutBox::GetUncombinedStyle(long position, wxTextAttrEx& style) +{ + return DoGetStyle(position, style, false); +} + +bool wxRichTextParagraphLayoutBox::GetUncombinedStyle(long position, wxRichTextAttr& style) +{ + wxTextAttrEx textAttrEx(style); + if (GetUncombinedStyle(position, textAttrEx)) + { + style = textAttrEx; + return true; + } + else + return false; +} + +/// Implementation helper for GetStyle. If combineStyles is true, combine base, paragraph and +/// context attributes. +bool wxRichTextParagraphLayoutBox::DoGetStyle(long position, wxTextAttrEx& style, bool combineStyles) +{ + wxRichTextObject* obj wxDUMMY_INITIALIZE(NULL); + + if (style.IsParagraphStyle()) + { + obj = GetParagraphAtPosition(position); + if (obj) + { +#if wxRICHTEXT_USE_DYNAMIC_STYLES + if (combineStyles) + { + // Start with the base style + style = GetAttributes(); + + // Apply the paragraph style + wxRichTextApplyStyle(style, obj->GetAttributes()); + } + else + style = obj->GetAttributes(); +#else + style = obj->GetAttributes(); +#endif + return true; + } + else + return false; + } + else + { + obj = GetLeafObjectAtPosition(position); + if (obj) + { +#if wxRICHTEXT_USE_DYNAMIC_STYLES + if (combineStyles) + { + wxRichTextParagraph* para = wxDynamicCast(obj->GetParent(), wxRichTextParagraph); + style = para ? para->GetCombinedAttributes(obj->GetAttributes()) : obj->GetAttributes(); + } + else + style = obj->GetAttributes(); +#else + style = obj->GetAttributes(); +#endif + return true; + } + else + return false; + } + return false; +} + /// Set default style bool wxRichTextParagraphLayoutBox::SetDefaultStyle(const wxTextAttrEx& style) { + // I don't think the default style should be combined with the previous + // default style. + m_defaultAttributes = style; + +#if 0 // keep the old attributes if the new style doesn't specify them unless the // new style is empty - then reset m_defaultStyle (as there is no other way // to do it) @@ -1680,7 +1782,7 @@ bool wxRichTextParagraphLayoutBox::SetDefaultStyle(const wxTextAttrEx& style) m_defaultAttributes = style; else m_defaultAttributes = wxTextAttrEx::CombineEx(style, m_defaultAttributes, NULL); - +#endif return true; } @@ -1715,7 +1817,12 @@ bool wxRichTextParagraphLayoutBox::HasCharacterAttributes(const wxRichTextRange& if (!child->GetRange().IsOutside(range) && child->IsKindOf(CLASSINFO(wxRichTextPlainText))) { foundCount ++; - if (wxTextAttrEqPartial(child->GetAttributes(), style, style.GetFlags())) +#if wxRICHTEXT_USE_DYNAMIC_STYLES + wxTextAttrEx textAttr = para->GetCombinedAttributes(child->GetAttributes()); +#else + const wxTextAttrEx& textAttr = child->GetAttributes(); +#endif + if (wxTextAttrEqPartial(textAttr, style, style.GetFlags())) matchingCount ++; } @@ -1759,8 +1866,16 @@ bool wxRichTextParagraphLayoutBox::HasParagraphAttributes(const wxRichTextRange& if (!para->GetRange().IsOutside(range)) { +#if wxRICHTEXT_USE_DYNAMIC_STYLES + wxTextAttrEx textAttr = GetAttributes(); + // Apply the paragraph style + wxRichTextApplyStyle(textAttr, para->GetAttributes()); + +#else + const wxTextAttrEx& textAttr = para->GetAttributes(); +#endif foundCount ++; - if (wxTextAttrEqPartial(para->GetAttributes(), style, style.GetFlags())) + if (wxTextAttrEqPartial(textAttr, style, style.GetFlags())) matchingCount ++; } } @@ -1829,6 +1944,40 @@ wxRichTextRange wxRichTextParagraphLayoutBox::GetInvalidRange(bool wholeParagrap return range; } +/// Apply the style sheet to the buffer, for example if the styles have changed. +bool wxRichTextParagraphLayoutBox::ApplyStyleSheet(wxRichTextStyleSheet* styleSheet) +{ + wxASSERT(styleSheet != NULL); + if (!styleSheet) + return false; + + int foundCount = 0; + + wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst(); + while (node) + { + wxRichTextParagraph* para = wxDynamicCast(node->GetData(), wxRichTextParagraph); + wxASSERT (para != NULL); + + if (para) + { + if (!para->GetAttributes().GetParagraphStyleName().IsEmpty()) + { + wxRichTextParagraphStyleDefinition* def = styleSheet->FindParagraphStyle(para->GetAttributes().GetParagraphStyleName()); + if (def) + { + para->GetAttributes() = def->GetStyle(); + foundCount ++; + } + } + } + + node = node->GetNext(); + } + return foundCount != 0; +} + + /*! * wxRichTextFragment class declaration * This is a lind of paragraph layout box used for storing @@ -1886,18 +2035,24 @@ wxRichTextParagraph::~wxRichTextParagraph() /// Draw the item bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range), const wxRichTextRange& selectionRange, const wxRect& WXUNUSED(rect), int WXUNUSED(descent), int style) { - // Draw the bullet, if any - if (GetAttributes().GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE) - { - if (GetAttributes().GetLeftSubIndent() != 0) - { - int spaceBeforePara = ConvertTenthsMMToPixels(dc, GetAttributes().GetParagraphSpacingBefore()); - // int spaceAfterPara = ConvertTenthsMMToPixels(dc, GetAttributes().GetParagraphSpacingAfter()); - int leftIndent = ConvertTenthsMMToPixels(dc, GetAttributes().GetLeftIndent()); - // int leftSubIndent = ConvertTenthsMMToPixels(dc, GetAttributes().GetLeftSubIndent()); - // int rightIndent = ConvertTenthsMMToPixels(dc, GetAttributes().GetRightIndent()); +#if wxRICHTEXT_USE_DYNAMIC_STYLES + wxTextAttrEx attr = GetCombinedAttributes(); +#else + const wxTextAttrEx& attr = GetAttributes(); +#endif - if (GetAttributes().GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_BITMAP) + // Draw the bullet, if any + if (attr.GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE) + { + if (attr.GetLeftSubIndent() != 0) + { + int spaceBeforePara = ConvertTenthsMMToPixels(dc, attr.GetParagraphSpacingBefore()); + // int spaceAfterPara = ConvertTenthsMMToPixels(dc, attr.GetParagraphSpacingAfter()); + int leftIndent = ConvertTenthsMMToPixels(dc, attr.GetLeftIndent()); + // int leftSubIndent = ConvertTenthsMMToPixels(dc, attr.GetLeftSubIndent()); + // int rightIndent = ConvertTenthsMMToPixels(dc, attr.GetRightIndent()); + + if (attr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_BITMAP) { // TODO } @@ -1906,11 +2061,11 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range), wxString bulletText = GetBulletText(); if (!bulletText.empty()) { - if (GetAttributes().GetFont().Ok()) - dc.SetFont(GetAttributes().GetFont()); + if (attr.GetFont().Ok()) + dc.SetFont(attr.GetFont()); - if (GetAttributes().GetTextColour().Ok()) - dc.SetTextForeground(GetAttributes().GetTextColour()); + if (attr.GetTextColour().Ok()) + dc.SetTextForeground(attr.GetTextColour()); dc.SetBackgroundMode(wxTRANSPARENT); @@ -1994,29 +2149,35 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range), /// Lay the item out bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) { +#if wxRICHTEXT_USE_DYNAMIC_STYLES + wxTextAttrEx attr = GetCombinedAttributes(); +#else + const wxTextAttrEx& attr = GetAttributes(); +#endif + // ClearLines(); // Increase the size of the paragraph due to spacing - int spaceBeforePara = ConvertTenthsMMToPixels(dc, GetAttributes().GetParagraphSpacingBefore()); - int spaceAfterPara = ConvertTenthsMMToPixels(dc, GetAttributes().GetParagraphSpacingAfter()); - int leftIndent = ConvertTenthsMMToPixels(dc, GetAttributes().GetLeftIndent()); - int leftSubIndent = ConvertTenthsMMToPixels(dc, GetAttributes().GetLeftSubIndent()); - int rightIndent = ConvertTenthsMMToPixels(dc, GetAttributes().GetRightIndent()); + int spaceBeforePara = ConvertTenthsMMToPixels(dc, attr.GetParagraphSpacingBefore()); + int spaceAfterPara = ConvertTenthsMMToPixels(dc, attr.GetParagraphSpacingAfter()); + int leftIndent = ConvertTenthsMMToPixels(dc, attr.GetLeftIndent()); + int leftSubIndent = ConvertTenthsMMToPixels(dc, attr.GetLeftSubIndent()); + int rightIndent = ConvertTenthsMMToPixels(dc, attr.GetRightIndent()); int lineSpacing = 0; // Let's assume line spacing of 10 is normal, 15 is 1.5, 20 is 2, etc. - if (GetAttributes().GetLineSpacing() > 10 && GetAttributes().GetFont().Ok()) + if (attr.GetLineSpacing() > 10 && attr.GetFont().Ok()) { - dc.SetFont(GetAttributes().GetFont()); - lineSpacing = (ConvertTenthsMMToPixels(dc, dc.GetCharHeight()) * GetAttributes().GetLineSpacing())/10; + dc.SetFont(attr.GetFont()); + lineSpacing = (ConvertTenthsMMToPixels(dc, dc.GetCharHeight()) * attr.GetLineSpacing())/10; } // Available space for text on each line differs. int availableTextSpaceFirstLine = rect.GetWidth() - leftIndent - rightIndent; // Bullets start the text at the same position as subsequent lines - if (GetAttributes().GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE) + if (attr.GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE) availableTextSpaceFirstLine -= leftSubIndent; int availableTextSpaceSubsequentLines = rect.GetWidth() - leftIndent - rightIndent - leftSubIndent; @@ -2027,7 +2188,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) // If we have a bullet in this paragraph, the start position for the first line's text // is actually leftIndent + leftSubIndent. - if (GetAttributes().GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE) + if (attr.GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE) startPositionFirstLine = startPositionSubsequentLines; //bool restrictWidth = wxRichTextHasStyle(style, wxRICHTEXT_FIXED_WIDTH); @@ -2175,8 +2336,8 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) if (lineHeight == 0) { - if (GetAttributes().GetFont().Ok()) - dc.SetFont(GetAttributes().GetFont()); + if (attr.GetFont().Ok()) + dc.SetFont(attr.GetFont()); lineHeight = dc.GetCharHeight(); } if (maxDescent == 0) @@ -2196,7 +2357,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) ClearUnusedLines(lineCount); // Apply styles to wrapped lines - ApplyParagraphStyle(rect); + ApplyParagraphStyle(attr, rect); SetCachedSize(wxSize(maxWidth, currentPosition.y + spaceBeforePara + spaceAfterPara)); @@ -2206,9 +2367,9 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) } /// Apply paragraph styles, such as centering, to wrapped lines -void wxRichTextParagraph::ApplyParagraphStyle(const wxRect& rect) +void wxRichTextParagraph::ApplyParagraphStyle(const wxTextAttrEx& attr, const wxRect& rect) { - if (!GetAttributes().HasAlignment()) + if (!attr.HasAlignment()) return; wxRichTextLineList::compatibility_iterator node = m_cachedLines.GetFirst(); @@ -2220,12 +2381,12 @@ void wxRichTextParagraph::ApplyParagraphStyle(const wxRect& rect) wxSize size = line->GetSize(); // centering, right-justification - if (GetAttributes().HasAlignment() && GetAttributes().GetAlignment() == wxTEXT_ALIGNMENT_CENTRE) + if (attr.HasAlignment() && GetAttributes().GetAlignment() == wxTEXT_ALIGNMENT_CENTRE) { pos.x = (rect.GetWidth() - size.x)/2 + pos.x; line->SetPosition(pos); } - else if (GetAttributes().HasAlignment() && GetAttributes().GetAlignment() == wxTEXT_ALIGNMENT_RIGHT) + else if (attr.HasAlignment() && GetAttributes().GetAlignment() == wxTEXT_ALIGNMENT_RIGHT) { pos.x = rect.GetRight() - size.x; line->SetPosition(pos); @@ -2873,6 +3034,39 @@ bool wxRichTextParagraph::ClearUnusedLines(int lineCount) return true; } +/// Get combined attributes of the base style, paragraph style and character style. We use this to dynamically +/// retrieve the actual style. +wxTextAttrEx wxRichTextParagraph::GetCombinedAttributes(const wxTextAttr& contentStyle) const +{ + wxTextAttrEx attr; + wxRichTextBuffer* buf = wxDynamicCast(GetParent(), wxRichTextBuffer); + if (buf) + { + attr = buf->GetBasicStyle(); + wxRichTextApplyStyle(attr, GetAttributes()); + } + else + attr = GetAttributes(); + + wxRichTextApplyStyle(attr, contentStyle); + return attr; +} + +/// Get combined attributes of the base style and paragraph style. +wxTextAttrEx wxRichTextParagraph::GetCombinedAttributes() const +{ + wxTextAttrEx attr; + wxRichTextBuffer* buf = wxDynamicCast(GetParent(), wxRichTextBuffer); + if (buf) + { + attr = buf->GetBasicStyle(); + wxRichTextApplyStyle(attr, GetAttributes()); + } + else + attr = GetAttributes(); + + return attr; +} /*! * wxRichTextLine @@ -2937,6 +3131,15 @@ wxRichTextPlainText::wxRichTextPlainText(const wxString& text, wxRichTextObject* /// Draw the item bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int descent, int WXUNUSED(style)) { +#if wxRICHTEXT_USE_DYNAMIC_STYLES + wxRichTextParagraph* para = wxDynamicCast(GetParent(), wxRichTextParagraph); + wxASSERT (para != NULL); + + wxTextAttrEx textAttr(para ? para->GetCombinedAttributes(GetAttributes()) : GetAttributes()); +#else + wxTextAttrEx textAttr(GetAttributes()); +#endif + int offset = GetRange().GetStart(); long len = range.GetLength(); @@ -2950,19 +3153,19 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR // Test for the optimized situations where all is selected, or none // is selected. - if (GetAttributes().GetFont().Ok()) - dc.SetFont(GetAttributes().GetFont()); + if (textAttr.GetFont().Ok()) + dc.SetFont(textAttr.GetFont()); // (a) All selected. if (selectionRange.GetStart() <= range.GetStart() && selectionRange.GetEnd() >= range.GetEnd()) { - DrawTabbedString(dc, rect,stringChunk, x, y, true); + DrawTabbedString(dc, textAttr, rect, stringChunk, x, y, true); } // (b) None selected. else if (selectionRange.GetEnd() < range.GetStart() || selectionRange.GetStart() > range.GetEnd()) { // Draw all unselected - DrawTabbedString(dc, rect,stringChunk, x, y, false); + DrawTabbedString(dc, textAttr, rect, stringChunk, x, y, false); } else { @@ -2981,7 +3184,7 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR wxLogDebug(wxT("Mid(%d, %d"), (int)(r1 - offset), (int)fragmentLen); wxString stringFragment = m_text.Mid(r1 - offset, fragmentLen); - DrawTabbedString(dc, rect,stringFragment, x, y, false); + DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, false); } // 2. Selected chunk, if any. @@ -2995,7 +3198,7 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR wxLogDebug(wxT("Mid(%d, %d"), (int)(s1 - offset), (int)fragmentLen); wxString stringFragment = m_text.Mid(s1 - offset, fragmentLen); - DrawTabbedString(dc, rect,stringFragment, x, y, true); + DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, true); } // 3. Remaining unselected chunk, if any @@ -3009,16 +3212,16 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR wxLogDebug(wxT("Mid(%d, %d"), (int)(s2 - offset), (int)fragmentLen); wxString stringFragment = m_text.Mid(s2 - offset, fragmentLen); - DrawTabbedString(dc, rect,stringFragment, x, y, false); + DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, false); } } return true; } -bool wxRichTextPlainText::DrawTabbedString(wxDC& dc,const wxRect& rect,wxString& str, wxCoord& x, wxCoord& y, bool selected) +bool wxRichTextPlainText::DrawTabbedString(wxDC& dc, const wxTextAttrEx& attr, const wxRect& rect,wxString& str, wxCoord& x, wxCoord& y, bool selected) { - wxArrayInt tab_array = GetAttributes().GetTabs(); + wxArrayInt tab_array = attr.GetTabs(); if (tab_array.IsEmpty()) { // create a default tab list at 10 mm each. @@ -3049,7 +3252,7 @@ bool wxRichTextPlainText::DrawTabbedString(wxDC& dc,const wxRect& rect,wxString& } else { - dc.SetTextForeground(GetAttributes().GetTextColour()); + dc.SetTextForeground(attr.GetTextColour()); dc.SetBackgroundMode(wxTRANSPARENT); } @@ -3091,11 +3294,21 @@ bool wxRichTextPlainText::DrawTabbedString(wxDC& dc,const wxRect& rect,wxString& return true; } + /// Lay the item out bool wxRichTextPlainText::Layout(wxDC& dc, const wxRect& WXUNUSED(rect), int WXUNUSED(style)) { - if (GetAttributes().GetFont().Ok()) - dc.SetFont(GetAttributes().GetFont()); +#if wxRICHTEXT_USE_DYNAMIC_STYLES + wxRichTextParagraph* para = wxDynamicCast(GetParent(), wxRichTextParagraph); + wxASSERT (para != NULL); + + wxTextAttrEx textAttr(para ? para->GetCombinedAttributes(GetAttributes()) : GetAttributes()); +#else + wxTextAttrEx textAttr(GetAttributes()); +#endif + + if (textAttr.GetFont().Ok()) + dc.SetFont(textAttr.GetFont()); wxCoord w, h; dc.GetTextExtent(m_text, & w, & h, & m_descent); @@ -3119,12 +3332,21 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz if (!range.IsWithin(GetRange())) return false; +#if wxRICHTEXT_USE_DYNAMIC_STYLES + wxRichTextParagraph* para = wxDynamicCast(GetParent(), wxRichTextParagraph); + wxASSERT (para != NULL); + + wxTextAttrEx textAttr(para ? para->GetCombinedAttributes(GetAttributes()) : GetAttributes()); +#else + wxTextAttrEx textAttr(GetAttributes()); +#endif + // 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 // formatted text by doing it in chunks according to the line ranges - if (GetAttributes().GetFont().Ok()) - dc.SetFont(GetAttributes().GetFont()); + if (textAttr.GetFont().Ok()) + dc.SetFont(textAttr.GetFont()); int startPos = range.GetStart() - GetRange().GetStart(); long len = range.GetLength(); @@ -3134,7 +3356,7 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz if (stringChunk.Find(wxT('\t')) >= 0) { // the string has a tab - wxArrayInt tab_array = GetAttributes().GetTabs(); + wxArrayInt tab_array = textAttr.GetTabs(); if (tab_array.IsEmpty()) { // create a default tab list at 10 mm each. @@ -3322,12 +3544,28 @@ void wxRichTextBuffer::Reset() } /// Submit command to insert the given text -bool wxRichTextBuffer::InsertTextWithUndo(long pos, const wxString& text, wxRichTextCtrl* ctrl) +bool wxRichTextBuffer::InsertTextWithUndo(long pos, const wxString& text, wxRichTextCtrl* ctrl, int flags) { wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Text"), wxRICHTEXT_INSERT, this, ctrl, false); - action->GetNewParagraphs().AddParagraphs(text); - if (action->GetNewParagraphs().GetChildCount() == 1) + wxTextAttrEx* p = NULL; + wxTextAttrEx paraAttr; + if (flags & wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE) + { + paraAttr = GetStyleForNewParagraph(pos); + if (!paraAttr.IsDefault()) + p = & paraAttr; + } + +#if wxRICHTEXT_USE_DYNAMIC_STYLES + wxTextAttrEx attr(GetDefaultStyle()); +#else + wxTextAttrEx attr(GetBasicStyle()); + wxRichTextApplyStyle(attr, GetDefaultStyle()); +#endif + + action->GetNewParagraphs().AddParagraphs(text, p); + if (action->GetNewParagraphs().GetChildCount() == 1 && text.Find(wxT("\n")) == wxNOT_FOUND) action->GetNewParagraphs().SetPartialParagraph(true); action->SetPosition(pos); @@ -3341,12 +3579,25 @@ bool wxRichTextBuffer::InsertTextWithUndo(long pos, const wxString& text, wxRich } /// Submit command to insert the given text -bool wxRichTextBuffer::InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl) +bool wxRichTextBuffer::InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl, int flags) { wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Text"), wxRICHTEXT_INSERT, this, ctrl, false); + wxTextAttrEx* p = NULL; + wxTextAttrEx paraAttr; + if (flags & wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE) + { + paraAttr = GetStyleForNewParagraph(pos); + if (!paraAttr.IsDefault()) + p = & paraAttr; + } + +#if wxRICHTEXT_USE_DYNAMIC_STYLES + wxTextAttrEx attr(GetDefaultStyle()); +#else wxTextAttrEx attr(GetBasicStyle()); wxRichTextApplyStyle(attr, GetDefaultStyle()); +#endif wxRichTextParagraph* newPara = new wxRichTextParagraph(wxEmptyString, this, & attr); action->GetNewParagraphs().AppendChild(newPara); @@ -3354,6 +3605,9 @@ bool wxRichTextBuffer::InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl) action->GetNewParagraphs().SetPartialParagraph(false); action->SetPosition(pos); + if (p) + newPara->SetAttributes(*p); + // Set the range we'll need to delete in Undo action->SetRange(wxRichTextRange(pos, pos)); @@ -3363,14 +3617,30 @@ bool wxRichTextBuffer::InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl) } /// Submit command to insert the given image -bool wxRichTextBuffer::InsertImageWithUndo(long pos, const wxRichTextImageBlock& imageBlock, wxRichTextCtrl* ctrl) +bool wxRichTextBuffer::InsertImageWithUndo(long pos, const wxRichTextImageBlock& imageBlock, wxRichTextCtrl* ctrl, int flags) { wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Image"), wxRICHTEXT_INSERT, this, ctrl, false); + wxTextAttrEx* p = NULL; + wxTextAttrEx paraAttr; + if (flags & wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE) + { + paraAttr = GetStyleForNewParagraph(pos); + if (!paraAttr.IsDefault()) + p = & paraAttr; + } + +#if wxRICHTEXT_USE_DYNAMIC_STYLES + wxTextAttrEx attr(GetDefaultStyle()); +#else wxTextAttrEx attr(GetBasicStyle()); wxRichTextApplyStyle(attr, GetDefaultStyle()); +#endif wxRichTextParagraph* newPara = new wxRichTextParagraph(this, & attr); + if (p) + newPara->SetAttributes(*p); + wxRichTextImage* imageObject = new wxRichTextImage(imageBlock, newPara); newPara->AppendChild(imageObject); action->GetNewParagraphs().AppendChild(newPara); @@ -3388,6 +3658,39 @@ bool wxRichTextBuffer::InsertImageWithUndo(long pos, const wxRichTextImageBlock& return true; } +/// Get the style that is appropriate for a new paragraph at this position. +/// If the previous paragraph has a paragraph style name, look up the next-paragraph +/// style. +wxRichTextAttr wxRichTextBuffer::GetStyleForNewParagraph(long pos, bool caretPosition) const +{ + wxRichTextParagraph* para = GetParagraphAtPosition(pos, caretPosition); + if (para) + { + if (!para->GetAttributes().GetParagraphStyleName().IsEmpty() && GetStyleSheet()) + { + wxRichTextParagraphStyleDefinition* paraDef = GetStyleSheet()->FindParagraphStyle(para->GetAttributes().GetParagraphStyleName()); + if (paraDef && !paraDef->GetNextStyle().IsEmpty()) + { + wxRichTextParagraphStyleDefinition* nextParaDef = GetStyleSheet()->FindParagraphStyle(paraDef->GetNextStyle()); + if (nextParaDef) + return nextParaDef->GetStyle(); + } + } + wxRichTextAttr attr(para->GetAttributes()); + int flags = attr.GetFlags(); + + // Eliminate character styles + flags &= ( (~ wxTEXT_ATTR_FONT) | + (~ wxTEXT_ATTR_TEXT_COLOUR) | + (~ wxTEXT_ATTR_BACKGROUND_COLOUR) ); + attr.SetFlags(flags); + + return attr; + } + else + return wxRichTextAttr(); +} + /// Submit command to delete this range bool wxRichTextBuffer::DeleteRangeWithUndo(const wxRichTextRange& range, long initialCaretPosition, long WXUNUSED(newCaretPositon), wxRichTextCtrl* ctrl) { @@ -4611,22 +4914,43 @@ bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxTextAttrEx& style) wxFont font = destStyle.GetFont(); if (style.GetFlags() & wxTEXT_ATTR_FONT_FACE) + { + destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_FACE); font.SetFaceName(style.GetFont().GetFaceName()); + } if (style.GetFlags() & wxTEXT_ATTR_FONT_SIZE) + { + destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_SIZE); font.SetPointSize(style.GetFont().GetPointSize()); + } if (style.GetFlags() & wxTEXT_ATTR_FONT_ITALIC) + { + destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_ITALIC); font.SetStyle(style.GetFont().GetStyle()); + } if (style.GetFlags() & wxTEXT_ATTR_FONT_WEIGHT) + { + destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_WEIGHT); font.SetWeight(style.GetFont().GetWeight()); + } if (style.GetFlags() & wxTEXT_ATTR_FONT_UNDERLINE) + { + destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_UNDERLINE); font.SetUnderlined(style.GetFont().GetUnderlined()); + } if (font != destStyle.GetFont()) + { + int oldFlags = destStyle.GetFlags(); + destStyle.SetFont(font); + + destStyle.SetFlags(oldFlags); + } } if ( style.GetTextColour().Ok() && style.HasTextColour()) @@ -4685,7 +5009,6 @@ bool wxRichTextApplyStyle(wxRichTextAttr& destStyle, const wxTextAttrEx& style) bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style) { - // Whole font. Avoiding setting individual attributes if possible, since // it recreates the font each time. if ((style.GetFlags() & (wxTEXT_ATTR_FONT)) == (wxTEXT_ATTR_FONT)) @@ -4698,22 +5021,43 @@ bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style) wxFont font = destStyle.GetFont(); if (style.GetFlags() & wxTEXT_ATTR_FONT_FACE) + { + destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_FACE); font.SetFaceName(style.GetFontFaceName()); + } if (style.GetFlags() & wxTEXT_ATTR_FONT_SIZE) + { + destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_SIZE); font.SetPointSize(style.GetFontSize()); + } if (style.GetFlags() & wxTEXT_ATTR_FONT_ITALIC) + { + destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_ITALIC); font.SetStyle(style.GetFontStyle()); + } if (style.GetFlags() & wxTEXT_ATTR_FONT_WEIGHT) + { + destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_WEIGHT); font.SetWeight(style.GetFontWeight()); + } if (style.GetFlags() & wxTEXT_ATTR_FONT_UNDERLINE) + { + destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_UNDERLINE); font.SetUnderlined(style.GetFontUnderlined()); + } if (font != destStyle.GetFont()) + { + int oldFlags = destStyle.GetFlags(); + destStyle.SetFont(font); + + destStyle.SetFlags(oldFlags); + } } if ( style.GetTextColour().Ok() && style.HasTextColour()) @@ -4867,6 +5211,33 @@ wxRichTextAttr::operator wxTextAttrEx () const return attr; } +// Equality test +bool wxRichTextAttr::operator== (const wxRichTextAttr& attr) const +{ + return GetFlags() == attr.GetFlags() && + + GetTextColour() == attr.GetTextColour() && + GetBackgroundColour() == attr.GetBackgroundColour() && + + GetAlignment() == attr.GetAlignment() && + GetLeftIndent() == attr.GetLeftIndent() && + GetLeftSubIndent() == attr.GetLeftSubIndent() && + GetRightIndent() == attr.GetRightIndent() && + //GetTabs() == attr.GetTabs() && + + GetParagraphSpacingAfter() == attr.GetParagraphSpacingAfter() && + GetParagraphSpacingBefore() == attr.GetParagraphSpacingBefore() && + GetLineSpacing() == attr.GetLineSpacing() && + GetCharacterStyleName() == attr.GetCharacterStyleName() && + GetParagraphStyleName() == attr.GetParagraphStyleName() && + + m_fontSize == attr.m_fontSize && + m_fontStyle == attr.m_fontStyle && + m_fontWeight == attr.m_fontWeight && + m_fontUnderlined == attr.m_fontUnderlined && + m_fontFaceName == attr.m_fontFaceName; +} + // Copy to a wxTextAttr void wxRichTextAttr::CopyTo(wxTextAttrEx& attr) const { @@ -4877,7 +5248,6 @@ void wxRichTextAttr::CopyTo(wxTextAttrEx& attr) const attr.SetLeftIndent(GetLeftIndent(), GetLeftSubIndent()); attr.SetRightIndent(GetRightIndent()); attr.SetFont(CreateFont()); - attr.SetFlags(GetFlags()); // Important: set after SetFont, since SetFont sets flags attr.SetParagraphSpacingAfter(m_paragraphSpacingAfter); attr.SetParagraphSpacingBefore(m_paragraphSpacingBefore); @@ -4888,6 +5258,7 @@ void wxRichTextAttr::CopyTo(wxTextAttrEx& attr) const attr.SetCharacterStyleName(m_characterStyleName); attr.SetParagraphStyleName(m_paragraphStyleName); + attr.SetFlags(GetFlags()); // Important: set after SetFont and others, since they set flags } // Create font from font attributes. diff --git a/src/richtext/richtextctrl.cpp b/src/richtext/richtextctrl.cpp index bb941820ce..b77d1a2fc1 100644 --- a/src/richtext/richtextctrl.cpp +++ b/src/richtext/richtextctrl.cpp @@ -22,11 +22,8 @@ #include "wx/richtext/richtextstyles.h" #ifndef WX_PRECOMP + #include "wx/wx.h" #include "wx/settings.h" - #include "wx/menu.h" - #include "wx/intl.h" - #include "wx/log.h" - #include "wx/stopwatch.h" #endif #include "wx/textfile.h" @@ -145,10 +142,13 @@ bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxString& va attributes.SetBackgroundColour(*wxWHITE); attributes.SetAlignment(wxTEXT_ALIGNMENT_LEFT); attributes.SetFlags(wxTEXT_ATTR_ALL); - - SetDefaultStyle(attributes); SetBasicStyle(attributes); + // The default attributes will be merged with base attributes, so + // can be empty to begin with + wxTextAttrEx defaultAttributes; + SetDefaultStyle(defaultAttributes); + SetBackgroundColour(*wxWHITE); SetBackgroundStyle(wxBG_STYLE_CUSTOM); @@ -466,7 +466,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) DeleteSelectedContent(& newPos); - GetBuffer().InsertNewlineWithUndo(newPos+1, this); + GetBuffer().InsertNewlineWithUndo(newPos+1, this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE); wxRichTextEvent cmdEvent( wxEVT_COMMAND_RICHTEXT_RETURN, @@ -545,7 +545,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) DeleteSelectedContent(& newPos); wxString str = (wxChar) event.GetKeyCode(); - GetBuffer().InsertTextWithUndo(newPos+1, str, this); + GetBuffer().InsertTextWithUndo(newPos+1, str, this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE); EndBatchUndo(); @@ -1528,7 +1528,7 @@ bool wxRichTextCtrl::RecreateBuffer(const wxSize& size) #if !wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE bool wxRichTextCtrl::LoadFile(const wxString& filename, int fileType) { - return DoLoadFile(filename, fileType); + return DoLoadFile(filename, fileType); } bool wxRichTextCtrl::SaveFile(const wxString& filename, int fileType) @@ -1744,6 +1744,7 @@ void wxRichTextCtrl::WriteText(const wxString& value) void wxRichTextCtrl::DoWriteText(const wxString& value, bool WXUNUSED(selectionOnly)) { wxString valueDos = wxTextFile::Translate(value, wxTextFileType_Unix); + GetBuffer().InsertTextWithUndo(m_caretPosition+1, valueDos, this); } @@ -1811,7 +1812,7 @@ void wxRichTextCtrl::Copy() { if (CanCopy()) { - wxRichTextRange range = GetSelectionRange(); + wxRichTextRange range = GetInternalSelectionRange(); GetBuffer().CopyToClipboard(range); } } @@ -1820,7 +1821,7 @@ void wxRichTextCtrl::Cut() { if (CanCut()) { - wxRichTextRange range = GetSelectionRange(); + wxRichTextRange range = GetInternalSelectionRange(); GetBuffer().CopyToClipboard(range); DeleteSelectedContent(); @@ -2258,7 +2259,7 @@ const wxTextAttr& wxRichTextCtrl::GetDefaultStyle() const bool wxRichTextCtrl::GetStyle(long position, wxTextAttr& style) { - wxTextAttrEx attr; + wxTextAttrEx attr(style); if (GetBuffer().GetStyle(position, attr)) { style = attr; @@ -2278,6 +2279,30 @@ bool wxRichTextCtrl::GetStyle(long position, wxRichTextAttr& style) return GetBuffer().GetStyle(position, style); } +/// Get the content (uncombined) attributes for this position. + +bool wxRichTextCtrl::GetUncombinedStyle(long position, wxTextAttr& style) +{ + wxTextAttrEx attr(style); + if (GetBuffer().GetUncombinedStyle(position, attr)) + { + style = attr; + return true; + } + else + return false; +} + +bool wxRichTextCtrl::GetUncombinedStyle(long position, wxTextAttrEx& style) +{ + return GetBuffer().GetUncombinedStyle(position, style); +} + +bool wxRichTextCtrl::GetUncombinedStyle(long position, wxRichTextAttr& style) +{ + return GetBuffer().GetUncombinedStyle(position, style); +} + /// Set font, and also the buffer attributes bool wxRichTextCtrl::SetFont(const wxFont& font) { @@ -2290,7 +2315,15 @@ bool wxRichTextCtrl::SetFont(const wxFont& font) wxTextAttrEx attr = GetBuffer().GetAttributes(); attr.SetFont(font); GetBuffer().SetBasicStyle(attr); + +#if !wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE + // Don't set the default style, since it will be inherited from + // the basic style. GetBuffer().SetDefaultStyle(attr); +#endif + + GetBuffer().Invalidate(wxRICHTEXT_ALL); + Refresh(false); return true; } @@ -2508,8 +2541,8 @@ bool wxRichTextCtrl::IsSelectionUnderlined() // to see what the effect would be if we started typing. wxRichTextAttr attr; attr.SetFlags(wxTEXT_ATTR_FONT_UNDERLINE); - long pos = GetAdjustedCaretPosition(GetCaretPosition()); + if (GetStyle(pos, attr)) { if (IsDefaultStyleShowing()) @@ -2618,6 +2651,24 @@ void wxRichTextCtrl::ApplyStyle(wxRichTextStyleDefinition* def) SetAndShowDefaultStyle(attr); } +/// Apply the style sheet to the buffer, for example if the styles have changed. +bool wxRichTextCtrl::ApplyStyleSheet(wxRichTextStyleSheet* styleSheet) +{ + if (!styleSheet) + styleSheet = GetBuffer().GetStyleSheet(); + if (!styleSheet) + return false; + + if (GetBuffer().ApplyStyleSheet(styleSheet)) + { + GetBuffer().Invalidate(wxRICHTEXT_ALL); + Refresh(false); + return true; + } + else + return false; +} + /// Sets the default style to the style under the cursor bool wxRichTextCtrl::SetDefaultStyleToCursorStyle() { @@ -2627,7 +2678,11 @@ bool wxRichTextCtrl::SetDefaultStyleToCursorStyle() // If at the start of a paragraph, use the next position. long pos = GetAdjustedCaretPosition(GetCaretPosition()); +#if wxRICHTEXT_USE_DYNAMIC_STYLES + if (GetUncombinedStyle(pos, attr)) +#else if (GetStyle(pos, attr)) +#endif { SetDefaultStyle(attr); return true; @@ -2676,7 +2731,7 @@ void wxRichTextCtrl::SetSelectionRange(const wxRichTextRange& range) range1.SetEnd(range1.GetEnd() - 1); wxASSERT( range1.GetStart() > range1.GetEnd() ); - + SetInternalSelectionRange(range1); } diff --git a/src/richtext/richtextstyles.cpp b/src/richtext/richtextstyles.cpp index 183daea53a..ada328a49e 100644 --- a/src/richtext/richtextstyles.cpp +++ b/src/richtext/richtextstyles.cpp @@ -13,7 +13,7 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop + #pragma hdrstop #endif #if wxUSE_RICHTEXT @@ -21,8 +21,7 @@ #include "wx/richtext/richtextstyles.h" #ifndef WX_PRECOMP - #include "wx/dcclient.h" - #include "wx/module.h" + #include "wx/wx.h" #endif #include "wx/filename.h" @@ -35,6 +34,38 @@ IMPLEMENT_CLASS(wxRichTextStyleDefinition, wxObject) IMPLEMENT_CLASS(wxRichTextCharacterStyleDefinition, wxRichTextStyleDefinition) IMPLEMENT_CLASS(wxRichTextParagraphStyleDefinition, wxRichTextStyleDefinition) +/*! + * A definition + */ + +void wxRichTextStyleDefinition::Copy(const wxRichTextStyleDefinition& def) +{ + m_name = def.m_name; + m_baseStyle = def.m_baseStyle; + m_style = def.m_style; +} + +bool wxRichTextStyleDefinition::Eq(const wxRichTextStyleDefinition& def) const +{ + return (m_name == def.m_name && m_baseStyle == def.m_baseStyle && m_style == def.m_style); +} + +/*! + * Paragraph style definition + */ + +void wxRichTextParagraphStyleDefinition::Copy(const wxRichTextParagraphStyleDefinition& def) +{ + wxRichTextStyleDefinition::Copy(def); + + m_nextStyle = def.m_nextStyle; +} + +bool wxRichTextParagraphStyleDefinition::operator ==(const wxRichTextParagraphStyleDefinition& def) const +{ + return (Eq(def) && m_nextStyle == def.m_nextStyle); +} + /*! * The style manager */ @@ -89,6 +120,48 @@ void wxRichTextStyleSheet::DeleteStyles() WX_CLEAR_LIST(wxList, m_paragraphStyleDefinitions); } +/// Add a definition to the character style list +bool wxRichTextStyleSheet::AddCharacterStyle(wxRichTextCharacterStyleDefinition* def) +{ + def->GetStyle().SetCharacterStyleName(def->GetName()); + return AddStyle(m_characterStyleDefinitions, def); +} + +/// Add a definition to the paragraph style list +bool wxRichTextStyleSheet::AddParagraphStyle(wxRichTextParagraphStyleDefinition* def) +{ + def->GetStyle().SetParagraphStyleName(def->GetName()); + return AddStyle(m_paragraphStyleDefinitions, def); +} + +/// Copy +void wxRichTextStyleSheet::Copy(const wxRichTextStyleSheet& sheet) +{ + DeleteStyles(); + + wxList::compatibility_iterator node; + + for (node = sheet.m_characterStyleDefinitions.GetFirst(); node; node = node->GetNext()) + { + wxRichTextCharacterStyleDefinition* def = (wxRichTextCharacterStyleDefinition*) node->GetData(); + AddCharacterStyle(new wxRichTextCharacterStyleDefinition(*def)); + } + + for (node = sheet.m_paragraphStyleDefinitions.GetFirst(); node; node = node->GetNext()) + { + wxRichTextParagraphStyleDefinition* def = (wxRichTextParagraphStyleDefinition*) node->GetData(); + AddParagraphStyle(new wxRichTextParagraphStyleDefinition(*def)); + } +} + +/// Equality +bool wxRichTextStyleSheet::operator==(const wxRichTextStyleSheet& WXUNUSED(sheet)) const +{ + // TODO + return false; +} + + #if wxUSE_HTML /*! * wxRichTextStyleListBox class declaration @@ -316,8 +389,10 @@ void wxRichTextStyleListBox::OnIdle(wxIdleEvent& event) { if (CanAutoSetSelection() && GetRichTextCtrl()) { - wxRichTextParagraph* para = GetRichTextCtrl()->GetBuffer().GetParagraphAtPosition(GetRichTextCtrl()->GetCaretPosition()); - wxRichTextObject* obj = GetRichTextCtrl()->GetBuffer().GetLeafObjectAtPosition(GetRichTextCtrl()->GetCaretPosition()); + int adjustedCaretPos = GetRichTextCtrl()->GetAdjustedCaretPosition(GetRichTextCtrl()->GetCaretPosition()); + + wxRichTextParagraph* para = GetRichTextCtrl()->GetBuffer().GetParagraphAtPosition(adjustedCaretPos); + wxRichTextObject* obj = GetRichTextCtrl()->GetBuffer().GetLeafObjectAtPosition(adjustedCaretPos); wxString styleName; @@ -483,8 +558,10 @@ void wxRichTextStyleComboCtrl::OnIdle(wxIdleEvent& event) { if (GetRichTextCtrl() && !IsPopupShown()) { - wxRichTextParagraph* para = GetRichTextCtrl()->GetBuffer().GetParagraphAtPosition(GetRichTextCtrl()->GetCaretPosition()); - wxRichTextObject* obj = GetRichTextCtrl()->GetBuffer().GetLeafObjectAtPosition(GetRichTextCtrl()->GetCaretPosition()); + int adjustedCaretPos = GetRichTextCtrl()->GetAdjustedCaretPosition(GetRichTextCtrl()->GetCaretPosition()); + + wxRichTextParagraph* para = GetRichTextCtrl()->GetBuffer().GetParagraphAtPosition(adjustedCaretPos); + wxRichTextObject* obj = GetRichTextCtrl()->GetBuffer().GetLeafObjectAtPosition(adjustedCaretPos); wxString styleName;