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;