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
This commit is contained in:
Julian Smart
2006-09-29 08:53:23 +00:00
parent 81c330c6f0
commit fe5aa22c17
7 changed files with 765 additions and 129 deletions

View File

@@ -102,6 +102,10 @@
#include "wx/cmdproc.h" #include "wx/cmdproc.h"
#include "wx/txtstrm.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 * File types
*/ */
@@ -161,6 +165,13 @@ class WXDLLIMPEXP_RICHTEXT wxTextAttrEx;
#define wxRICHTEXT_FORMATTED 0x01 #define wxRICHTEXT_FORMATTED 0x01
#define wxRICHTEXT_UNFORMATTED 0x02 #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 * Extra formatting flags not in wxTextAttr
*/ */
@@ -378,6 +389,9 @@ public:
// Assignment from a wxTextAttrEx object. // Assignment from a wxTextAttrEx object.
void operator= (const wxTextAttrEx& attr); void operator= (const wxTextAttrEx& attr);
// Equality test
bool operator== (const wxRichTextAttr& attr) const;
// Making a wxTextAttrEx object. // Making a wxTextAttrEx object.
operator wxTextAttrEx () const ; operator wxTextAttrEx () const ;
@@ -853,13 +867,13 @@ public:
virtual void Reset(); virtual void Reset();
/// Convenience function to add a paragraph of text /// 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 /// 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. /// 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 /// Get the line at the given position. If caretPosition is true, the position is
/// a caret position, which is normally a smaller number. /// 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 wxRichTextAttr& style, bool withUndo = true);
virtual bool SetStyle(const wxRichTextRange& range, const wxTextAttrEx& 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, wxTextAttrEx& style);
virtual bool GetStyle(long position, wxRichTextAttr& 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 /// 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 /// 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 /// 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'. /// Make a copy of the fragment corresponding to the given range, putting it in 'fragment'.
virtual bool CopyFragment(const wxRichTextRange& range, wxRichTextFragment& fragment); virtual bool CopyFragment(const wxRichTextRange& range, wxRichTextFragment& fragment);
/// Apply the style sheet to the buffer, for example if the styles have changed.
virtual bool ApplyStyleSheet(wxRichTextStyleSheet* styleSheet);
/// Copy /// Copy
void Copy(const wxRichTextParagraphLayoutBox& obj); void Copy(const wxRichTextParagraphLayoutBox& obj);
@@ -1161,7 +1186,7 @@ public:
// Implementation // Implementation
/// Apply paragraph styles such as centering to the wrapped lines /// 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 /// Insert text at the given position
virtual bool InsertText(long pos, const wxString& text); virtual bool InsertText(long pos, const wxString& text);
@@ -1196,6 +1221,13 @@ public:
/// Clear remaining unused line objects, if any /// Clear remaining unused line objects, if any
bool ClearUnusedLines(int lineCount); 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: protected:
/// The lines that make up the wrapped paragraph /// The lines that make up the wrapped paragraph
wxRichTextLineList m_cachedLines; wxRichTextLineList m_cachedLines;
@@ -1269,7 +1301,7 @@ public:
/// Clone /// Clone
virtual wxRichTextObject* Clone() const { return new wxRichTextPlainText(*this); } virtual wxRichTextObject* Clone() const { return new wxRichTextPlainText(*this); }
private: 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: protected:
wxString m_text; wxString m_text;
@@ -1623,13 +1655,13 @@ public:
virtual wxRichTextObject* Clone() const { return new wxRichTextBuffer(*this); } virtual wxRichTextObject* Clone() const { return new wxRichTextBuffer(*this); }
/// Submit command to insert the given text /// 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 /// 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 /// 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 /// Submit command to delete this range
bool DeleteRangeWithUndo(const wxRichTextRange& range, long initialCaretPosition, long newCaretPositon, wxRichTextCtrl* ctrl); bool DeleteRangeWithUndo(const wxRichTextRange& range, long initialCaretPosition, long newCaretPositon, wxRichTextCtrl* ctrl);
@@ -1638,6 +1670,11 @@ public:
void Modify(bool modify = true) { m_modified = modify; } void Modify(bool modify = true) { m_modified = modify; }
bool IsModified() const { return m_modified; } 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 /// Dumps contents of buffer for debugging purposes
virtual void Dump(); virtual void Dump();
virtual void Dump(wxTextOutputStream& stream) { wxRichTextParagraphLayoutBox::Dump(stream); } virtual void Dump(wxTextOutputStream& stream) { wxRichTextParagraphLayoutBox::Dump(stream); }

View File

@@ -188,6 +188,12 @@ public:
virtual bool GetStyle(long position, wxTextAttr& style); virtual bool GetStyle(long position, wxTextAttr& style);
virtual bool GetStyle(long position, wxTextAttrEx& style); virtual bool GetStyle(long position, wxTextAttrEx& style);
virtual bool GetStyle(long position, wxRichTextAttr& 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 wxTextAttrEx& style);
virtual bool SetDefaultStyle(const wxTextAttr& style); virtual bool SetDefaultStyle(const wxTextAttr& style);
@@ -530,6 +536,9 @@ public:
void SetStyleSheet(wxRichTextStyleSheet* styleSheet) { GetBuffer().SetStyleSheet(styleSheet); } void SetStyleSheet(wxRichTextStyleSheet* styleSheet) { GetBuffer().SetStyleSheet(styleSheet); }
wxRichTextStyleSheet* GetStyleSheet() const { return GetBuffer().GetStyleSheet(); } 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 // Command handlers
void Command(wxCommandEvent& event); void Command(wxCommandEvent& event);
@@ -595,8 +604,6 @@ public:
/// Scrolling /// Scrolling
void OnScroll(wxScrollWinEvent& event); void OnScroll(wxScrollWinEvent& event);
// Implementation
/// Set font, and also default attributes /// Set font, and also default attributes
virtual bool SetFont(const wxFont& font); virtual bool SetFont(const wxFont& font);
@@ -717,6 +724,8 @@ public:
SetCaretPositionForDefaultStyle(GetCaretPosition()); SetCaretPositionForDefaultStyle(GetCaretPosition());
} }
// Implementation
#if wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE #if wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE
WX_FORWARD_TO_SCROLL_HELPER() WX_FORWARD_TO_SCROLL_HELPER()
#endif #endif
@@ -845,4 +854,3 @@ typedef void (wxEvtHandler::*wxRichTextEventFunction)(wxRichTextEvent&);
#endif #endif
// _WX_RICHTEXTCTRL_H_ // _WX_RICHTEXTCTRL_H_

View File

@@ -47,10 +47,15 @@ public:
// Constructors // Constructors
wxRichTextStyleDefinition(const wxRichTextStyleDefinition& def) { Copy(def); }
wxRichTextStyleDefinition(const wxString& name = wxEmptyString) { Init(); m_name = name; } wxRichTextStyleDefinition(const wxString& name = wxEmptyString) { Init(); m_name = name; }
virtual ~wxRichTextStyleDefinition() {} virtual ~wxRichTextStyleDefinition() {}
void Init() {} 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. /// The name of the style.
void SetName(const wxString& name) { m_name = name; } void SetName(const wxString& name) { m_name = name; }
@@ -82,6 +87,7 @@ public:
// Constructors // Constructors
wxRichTextCharacterStyleDefinition(const wxRichTextCharacterStyleDefinition& def): wxRichTextStyleDefinition(def) {}
wxRichTextCharacterStyleDefinition(const wxString& name = wxEmptyString): wxRichTextCharacterStyleDefinition(const wxString& name = wxEmptyString):
wxRichTextStyleDefinition(name) {} wxRichTextStyleDefinition(name) {}
virtual ~wxRichTextCharacterStyleDefinition() {} virtual ~wxRichTextCharacterStyleDefinition() {}
@@ -100,6 +106,7 @@ public:
// Constructors // Constructors
wxRichTextParagraphStyleDefinition(const wxRichTextParagraphStyleDefinition& def): wxRichTextStyleDefinition(def) { m_nextStyle = def.m_nextStyle; }
wxRichTextParagraphStyleDefinition(const wxString& name = wxEmptyString): wxRichTextParagraphStyleDefinition(const wxString& name = wxEmptyString):
wxRichTextStyleDefinition(name) {} wxRichTextStyleDefinition(name) {}
virtual ~wxRichTextParagraphStyleDefinition() {} virtual ~wxRichTextParagraphStyleDefinition() {}
@@ -108,6 +115,10 @@ public:
void SetNextStyle(const wxString& name) { m_nextStyle = name; } void SetNextStyle(const wxString& name) { m_nextStyle = name; }
const wxString& GetNextStyle() const { return m_nextStyle; } 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: protected:
/// The next style to use when adding a paragraph after this style. /// The next style to use when adding a paragraph after this style.
@@ -124,29 +135,39 @@ class WXDLLIMPEXP_RICHTEXT wxRichTextStyleSheet: public wxObject
public: public:
/// Constructors /// Constructors
wxRichTextStyleSheet(const wxRichTextStyleSheet& sheet) { Copy(sheet); }
wxRichTextStyleSheet() { Init(); } wxRichTextStyleSheet() { Init(); }
virtual ~wxRichTextStyleSheet() { DeleteStyles(); } virtual ~wxRichTextStyleSheet() { DeleteStyles(); }
/// Initialisation /// Initialisation
void Init(); 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 /// 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 /// 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 /// Remove a character style
bool RemoveCharacterStyle(wxRichTextStyleDefinition* def, bool deleteStyle = false) { return RemoveStyle(m_characterStyleDefinitions, def, deleteStyle); } bool RemoveCharacterStyle(wxRichTextStyleDefinition* def, bool deleteStyle = false) { return RemoveStyle(m_characterStyleDefinitions, def, deleteStyle); }
/// Remove a paragraph style /// 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 /// Find a character definition by name
wxRichTextCharacterStyleDefinition* FindCharacterStyle(const wxString& name) const { return (wxRichTextCharacterStyleDefinition*) FindStyle(m_characterStyleDefinitions, name); } wxRichTextCharacterStyleDefinition* FindCharacterStyle(const wxString& name) const { return (wxRichTextCharacterStyleDefinition*) FindStyle(m_characterStyleDefinitions, name); }
/// Find a paragraph definition by 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. /// Return the number of character styes.
size_t GetCharacterStyleCount() const { return m_characterStyleDefinitions.GetCount(); } size_t GetCharacterStyleCount() const { return m_characterStyleDefinitions.GetCount(); }

View File

@@ -139,6 +139,8 @@ public:
void OnViewHTML(wxCommandEvent& event); void OnViewHTML(wxCommandEvent& event);
void OnSwitchStyleSheets(wxCommandEvent& event);
// Forward command events to the current rich text control, if any // Forward command events to the current rich text control, if any
bool ProcessEvent(wxEvent& event); bool ProcessEvent(wxEvent& event);
@@ -179,7 +181,12 @@ enum
ID_FORMAT_LINE_SPACING_DOUBLE, ID_FORMAT_LINE_SPACING_DOUBLE,
ID_FORMAT_LINE_SPACING_SINGLE, 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_FORMAT_PARAGRAPH_SPACING_LESS, MyFrame::OnParagraphSpacingLess)
EVT_MENU(ID_VIEW_HTML, MyFrame::OnViewHTML) EVT_MENU(ID_VIEW_HTML, MyFrame::OnViewHTML)
EVT_MENU(ID_SWITCH_STYLE_SHEETS, MyFrame::OnSwitchStyleSheets)
END_EVENT_TABLE() END_EVENT_TABLE()
// Create a new application object: this macro will allow wxWidgets to create // 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->Append(ID_FORMAT_LINE_SPACING_DOUBLE, _("Double Line Spacing"));
formatMenu->AppendSeparator(); formatMenu->AppendSeparator();
formatMenu->Append(ID_FORMAT_FONT, _("&Font...")); 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... // now append the freshly created menu to the menu bar...
wxMenuBar *menuBar = new wxMenuBar(); wxMenuBar *menuBar = new wxMenuBar();
@@ -490,7 +500,7 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
toolBar->AddSeparator(); toolBar->AddSeparator();
toolBar->AddTool(ID_FORMAT_FONT, wxBitmap(font_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Font")); 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->AddControl(combo);
toolBar->Realize(); toolBar->Realize();
@@ -501,16 +511,18 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
wxFont boldFont = wxFont(12, wxROMAN, wxNORMAL, wxBOLD); wxFont boldFont = wxFont(12, wxROMAN, wxNORMAL, wxBOLD);
wxFont italicFont = wxFont(12, wxROMAN, wxITALIC, wxNORMAL); 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); wxFont font(12, wxROMAN, wxNORMAL, wxNORMAL);
m_richTextCtrl->SetFont(font); m_richTextCtrl->SetFont(font);
m_richTextCtrl->SetStyleSheet(wxGetApp().GetStyleSheet());
combo->SetStyleSheet(wxGetApp().GetStyleSheet()); combo->SetStyleSheet(wxGetApp().GetStyleSheet());
combo->SetRichTextCtrl(m_richTextCtrl); combo->SetRichTextCtrl(m_richTextCtrl);
combo->UpdateStyles(); combo->UpdateStyles();
wxRichTextStyleListBox* styleListBox = new wxRichTextStyleListBox(splitter, wxID_ANY); wxRichTextStyleListBox* styleListBox = new wxRichTextStyleListBox(splitter, ID_RICHTEXT_STYLE_LIST);
wxSize display = wxGetDisplaySize(); wxSize display = wxGetDisplaySize();
if ( is_pda && ( display.GetWidth() < display.GetHeight() ) ) if ( is_pda && ( display.GetWidth() < display.GetHeight() ) )
@@ -1073,3 +1085,58 @@ void MyFrame::OnViewHTML(wxCommandEvent& WXUNUSED(event))
dialog.ShowModal(); 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();
}

View File

@@ -81,11 +81,12 @@ void wxRichTextObject::Copy(const wxRichTextObject& obj)
m_range = obj.m_range; m_range = obj.m_range;
m_attributes = obj.m_attributes; m_attributes = obj.m_attributes;
m_descent = obj.m_descent; m_descent = obj.m_descent;
/*
if (!m_attributes.GetFont().Ok()) if (!m_attributes.GetFont().Ok())
wxLogDebug(wxT("No font!")); wxLogDebug(wxT("No font!"));
if (!obj.m_attributes.GetFont().Ok()) if (!obj.m_attributes.GetFont().Ok())
wxLogDebug(wxT("Parent has no font!")); wxLogDebug(wxT("Parent has no font!"));
*/
} }
void wxRichTextObject::SetMargins(int margin) void wxRichTextObject::SetMargins(int margin)
@@ -221,7 +222,9 @@ void wxRichTextCompositeObject::Copy(const wxRichTextCompositeObject& obj)
while (node) while (node)
{ {
wxRichTextObject* child = node->GetData(); wxRichTextObject* child = node->GetData();
m_children.Append(child->Clone()); wxRichTextObject* newChild = child->Clone();
newChild->SetParent(this);
m_children.Append(newChild);
node = node->GetNext(); node = node->GetNext();
} }
@@ -869,16 +872,23 @@ wxSize wxRichTextParagraphLayoutBox::GetLineSizeAtPosition(long pos, bool caretP
/// Convenience function to add a paragraph of text /// 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()); wxTextAttrEx style(GetAttributes());
// Apply default style. If the style has no attributes set, // Apply default style. If the style has no attributes set,
// then the attributes will remain the 'basic style' (i.e. the // then the attributes will remain the 'basic style' (i.e. the
// layout box's style). // layout box's style).
wxRichTextApplyStyle(style, GetDefaultStyle()); wxRichTextApplyStyle(style, GetDefaultStyle());
#endif
wxRichTextParagraph* para = new wxRichTextParagraph(text, this, & style); wxRichTextParagraph* para = new wxRichTextParagraph(text, this, & style);
if (paraStyle)
para->SetAttributes(*paraStyle);
AppendChild(para); AppendChild(para);
@@ -889,9 +899,15 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraph(const wxString& text)
} }
/// Adds multiple paragraphs, based on newlines. /// 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()); wxTextAttrEx style(GetAttributes());
//wxLogDebug("Initial style = %s", style.GetFont().GetFaceName()); //wxLogDebug("Initial style = %s", style.GetFont().GetFaceName());
//wxLogDebug("Initial size = %d", style.GetFont().GetPointSize()); //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("Style after applying default style = %s", style.GetFont().GetFaceName());
//wxLogDebug("Size after applying default style = %d", style.GetFont().GetPointSize()); //wxLogDebug("Size after applying default style = %d", style.GetFont().GetPointSize());
#endif
wxRichTextParagraph* firstPara = NULL; wxRichTextParagraph* firstPara = NULL;
wxRichTextParagraph* lastPara = NULL; wxRichTextParagraph* lastPara = NULL;
@@ -916,6 +933,8 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraphs(const wxString& text
if (ch == wxT('\n') || ch == wxT('\r')) if (ch == wxT('\n') || ch == wxT('\r'))
{ {
wxRichTextParagraph* para = new wxRichTextParagraph(line, this, & style); wxRichTextParagraph* para = new wxRichTextParagraph(line, this, & style);
if (paraStyle)
para->SetAttributes(*paraStyle);
AppendChild(para); AppendChild(para);
if (!firstPara) if (!firstPara)
@@ -931,6 +950,9 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraphs(const wxString& text
if (!line.empty()) if (!line.empty())
{ {
lastPara = new wxRichTextParagraph(line, this, & style); lastPara = new wxRichTextParagraph(line, this, & style);
if (paraStyle)
lastPara->SetAttributes(*paraStyle);
//wxLogDebug("Para Face = %s", lastPara->GetAttributes().GetFont().GetFaceName()); //wxLogDebug("Para Face = %s", lastPara->GetAttributes().GetFont().GetFaceName());
AppendChild(lastPara); AppendChild(lastPara);
} }
@@ -952,19 +974,28 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraphs(const wxString& text
} }
/// Convenience function to add an image /// 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()); wxTextAttrEx style(GetAttributes());
// Apply default style. If the style has no attributes set, // Apply default style. If the style has no attributes set,
// then the attributes will remain the 'basic style' (i.e. the // then the attributes will remain the 'basic style' (i.e. the
// layout box's style). // layout box's style).
wxRichTextApplyStyle(style, GetDefaultStyle()); wxRichTextApplyStyle(style, GetDefaultStyle());
#endif
wxRichTextParagraph* para = new wxRichTextParagraph(this, & style); wxRichTextParagraph* para = new wxRichTextParagraph(this, & style);
AppendChild(para); AppendChild(para);
para->AppendChild(new wxRichTextImage(image, this)); para->AppendChild(new wxRichTextImage(image, this));
if (paraStyle)
para->SetAttributes(*paraStyle);
UpdateRanges(); UpdateRanges();
SetDirty(true); SetDirty(true);
@@ -1112,7 +1143,9 @@ bool wxRichTextParagraphLayoutBox::InsertFragment(long position, wxRichTextFragm
if (finalPara->GetChildCount() == 0) if (finalPara->GetChildCount() == 0)
{ {
wxRichTextPlainText* text = new wxRichTextPlainText(wxEmptyString); wxRichTextPlainText* text = new wxRichTextPlainText(wxEmptyString);
#if !wxRICHTEXT_USE_DYNAMIC_STYLES
text->SetAttributes(finalPara->GetAttributes()); text->SetAttributes(finalPara->GetAttributes());
#endif
finalPara->AppendChild(text); finalPara->AppendChild(text);
} }
@@ -1387,8 +1420,8 @@ wxString wxRichTextParagraphLayoutBox::GetTextForRange(const wxRichTextRange& ra
wxRichTextObject* child = node->GetData(); wxRichTextObject* child = node->GetData();
if (!child->GetRange().IsOutside(range)) if (!child->GetRange().IsOutside(range))
{ {
if (lineCount > 0) // if (lineCount > 0)
text += wxT("\n"); // text += wxT("\n");
wxRichTextRange childRange = range; wxRichTextRange childRange = range;
childRange.LimitTo(child->GetRange()); childRange.LimitTo(child->GetRange());
@@ -1396,6 +1429,9 @@ wxString wxRichTextParagraphLayoutBox::GetTextForRange(const wxRichTextRange& ra
text += childText; text += childText;
if (childRange.GetEnd() == child->GetRange().GetEnd())
text += wxT("\n");
lineCount ++; lineCount ++;
} }
node = node->GetNext(); node = node->GetNext();
@@ -1557,7 +1593,15 @@ bool wxRichTextParagraphLayoutBox::SetStyle(const wxRichTextRange& range, const
if (paragraphStyle) if (paragraphStyle)
wxRichTextApplyStyle(newPara->GetAttributes(), style); 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()) if (characterStyle && range.GetStart() != newPara->GetRange().GetEnd())
#endif
{ {
wxRichTextRange childRange(range); wxRichTextRange childRange(range);
childRange.LimitTo(newPara->GetRange()); childRange.LimitTo(newPara->GetRange());
@@ -1635,44 +1679,102 @@ bool wxRichTextParagraphLayoutBox::SetStyle(const wxRichTextRange& range, const
/// Get the text attributes for this position. /// Get the text attributes for this position.
bool wxRichTextParagraphLayoutBox::GetStyle(long position, wxTextAttrEx& style) bool wxRichTextParagraphLayoutBox::GetStyle(long position, wxTextAttrEx& style)
{ {
wxRichTextObject* obj wxDUMMY_INITIALIZE(NULL); return DoGetStyle(position, style, true);
}
if (style.IsParagraphStyle()) /// Get the text attributes for this position.
obj = GetParagraphAtPosition(position); bool wxRichTextParagraphLayoutBox::GetStyle(long position, wxRichTextAttr& style)
else
obj = GetLeafObjectAtPosition(position);
if (obj)
{ {
style = obj->GetAttributes(); wxTextAttrEx textAttrEx(style);
if (GetStyle(position, textAttrEx))
{
style = textAttrEx;
return true; return true;
} }
else else
return false; return false;
} }
/// Get the text attributes for this position. /// Get the content (uncombined) attributes for this position.
bool wxRichTextParagraphLayoutBox::GetStyle(long position, wxRichTextAttr& style) 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); wxRichTextObject* obj wxDUMMY_INITIALIZE(NULL);
if (style.IsParagraphStyle()) if (style.IsParagraphStyle())
{
obj = GetParagraphAtPosition(position); obj = GetParagraphAtPosition(position);
else
obj = GetLeafObjectAtPosition(position);
if (obj) 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(); style = obj->GetAttributes();
#else
style = obj->GetAttributes();
#endif
return true; return true;
} }
else else
return false; 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 /// Set default style
bool wxRichTextParagraphLayoutBox::SetDefaultStyle(const wxTextAttrEx& 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 // 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 // new style is empty - then reset m_defaultStyle (as there is no other way
// to do it) // to do it)
@@ -1680,7 +1782,7 @@ bool wxRichTextParagraphLayoutBox::SetDefaultStyle(const wxTextAttrEx& style)
m_defaultAttributes = style; m_defaultAttributes = style;
else else
m_defaultAttributes = wxTextAttrEx::CombineEx(style, m_defaultAttributes, NULL); m_defaultAttributes = wxTextAttrEx::CombineEx(style, m_defaultAttributes, NULL);
#endif
return true; return true;
} }
@@ -1715,7 +1817,12 @@ bool wxRichTextParagraphLayoutBox::HasCharacterAttributes(const wxRichTextRange&
if (!child->GetRange().IsOutside(range) && child->IsKindOf(CLASSINFO(wxRichTextPlainText))) if (!child->GetRange().IsOutside(range) && child->IsKindOf(CLASSINFO(wxRichTextPlainText)))
{ {
foundCount ++; 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 ++; matchingCount ++;
} }
@@ -1759,8 +1866,16 @@ bool wxRichTextParagraphLayoutBox::HasParagraphAttributes(const wxRichTextRange&
if (!para->GetRange().IsOutside(range)) 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 ++; foundCount ++;
if (wxTextAttrEqPartial(para->GetAttributes(), style, style.GetFlags())) if (wxTextAttrEqPartial(textAttr, style, style.GetFlags()))
matchingCount ++; matchingCount ++;
} }
} }
@@ -1829,6 +1944,40 @@ wxRichTextRange wxRichTextParagraphLayoutBox::GetInvalidRange(bool wholeParagrap
return range; 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 * wxRichTextFragment class declaration
* This is a lind of paragraph layout box used for storing * This is a lind of paragraph layout box used for storing
@@ -1886,18 +2035,24 @@ wxRichTextParagraph::~wxRichTextParagraph()
/// Draw the item /// Draw the item
bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range), const wxRichTextRange& selectionRange, const wxRect& WXUNUSED(rect), int WXUNUSED(descent), int style) 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 wxRICHTEXT_USE_DYNAMIC_STYLES
if (GetAttributes().GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE) wxTextAttrEx attr = GetCombinedAttributes();
{ #else
if (GetAttributes().GetLeftSubIndent() != 0) const wxTextAttrEx& attr = GetAttributes();
{ #endif
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 (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 // TODO
} }
@@ -1906,11 +2061,11 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range),
wxString bulletText = GetBulletText(); wxString bulletText = GetBulletText();
if (!bulletText.empty()) if (!bulletText.empty())
{ {
if (GetAttributes().GetFont().Ok()) if (attr.GetFont().Ok())
dc.SetFont(GetAttributes().GetFont()); dc.SetFont(attr.GetFont());
if (GetAttributes().GetTextColour().Ok()) if (attr.GetTextColour().Ok())
dc.SetTextForeground(GetAttributes().GetTextColour()); dc.SetTextForeground(attr.GetTextColour());
dc.SetBackgroundMode(wxTRANSPARENT); dc.SetBackgroundMode(wxTRANSPARENT);
@@ -1994,29 +2149,35 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range),
/// Lay the item out /// Lay the item out
bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) 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(); // ClearLines();
// Increase the size of the paragraph due to spacing // Increase the size of the paragraph due to spacing
int spaceBeforePara = ConvertTenthsMMToPixels(dc, GetAttributes().GetParagraphSpacingBefore()); int spaceBeforePara = ConvertTenthsMMToPixels(dc, attr.GetParagraphSpacingBefore());
int spaceAfterPara = ConvertTenthsMMToPixels(dc, GetAttributes().GetParagraphSpacingAfter()); int spaceAfterPara = ConvertTenthsMMToPixels(dc, attr.GetParagraphSpacingAfter());
int leftIndent = ConvertTenthsMMToPixels(dc, GetAttributes().GetLeftIndent()); int leftIndent = ConvertTenthsMMToPixels(dc, attr.GetLeftIndent());
int leftSubIndent = ConvertTenthsMMToPixels(dc, GetAttributes().GetLeftSubIndent()); int leftSubIndent = ConvertTenthsMMToPixels(dc, attr.GetLeftSubIndent());
int rightIndent = ConvertTenthsMMToPixels(dc, GetAttributes().GetRightIndent()); int rightIndent = ConvertTenthsMMToPixels(dc, attr.GetRightIndent());
int lineSpacing = 0; int lineSpacing = 0;
// Let's assume line spacing of 10 is normal, 15 is 1.5, 20 is 2, etc. // 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()); dc.SetFont(attr.GetFont());
lineSpacing = (ConvertTenthsMMToPixels(dc, dc.GetCharHeight()) * GetAttributes().GetLineSpacing())/10; lineSpacing = (ConvertTenthsMMToPixels(dc, dc.GetCharHeight()) * attr.GetLineSpacing())/10;
} }
// Available space for text on each line differs. // Available space for text on each line differs.
int availableTextSpaceFirstLine = rect.GetWidth() - leftIndent - rightIndent; int availableTextSpaceFirstLine = rect.GetWidth() - leftIndent - rightIndent;
// Bullets start the text at the same position as subsequent lines // 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; availableTextSpaceFirstLine -= leftSubIndent;
int availableTextSpaceSubsequentLines = rect.GetWidth() - leftIndent - rightIndent - 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 // If we have a bullet in this paragraph, the start position for the first line's text
// is actually leftIndent + leftSubIndent. // is actually leftIndent + leftSubIndent.
if (GetAttributes().GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE) if (attr.GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE)
startPositionFirstLine = startPositionSubsequentLines; startPositionFirstLine = startPositionSubsequentLines;
//bool restrictWidth = wxRichTextHasStyle(style, wxRICHTEXT_FIXED_WIDTH); //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 (lineHeight == 0)
{ {
if (GetAttributes().GetFont().Ok()) if (attr.GetFont().Ok())
dc.SetFont(GetAttributes().GetFont()); dc.SetFont(attr.GetFont());
lineHeight = dc.GetCharHeight(); lineHeight = dc.GetCharHeight();
} }
if (maxDescent == 0) if (maxDescent == 0)
@@ -2196,7 +2357,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
ClearUnusedLines(lineCount); ClearUnusedLines(lineCount);
// Apply styles to wrapped lines // Apply styles to wrapped lines
ApplyParagraphStyle(rect); ApplyParagraphStyle(attr, rect);
SetCachedSize(wxSize(maxWidth, currentPosition.y + spaceBeforePara + spaceAfterPara)); 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 /// 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; return;
wxRichTextLineList::compatibility_iterator node = m_cachedLines.GetFirst(); wxRichTextLineList::compatibility_iterator node = m_cachedLines.GetFirst();
@@ -2220,12 +2381,12 @@ void wxRichTextParagraph::ApplyParagraphStyle(const wxRect& rect)
wxSize size = line->GetSize(); wxSize size = line->GetSize();
// centering, right-justification // 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; pos.x = (rect.GetWidth() - size.x)/2 + pos.x;
line->SetPosition(pos); 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; pos.x = rect.GetRight() - size.x;
line->SetPosition(pos); line->SetPosition(pos);
@@ -2873,6 +3034,39 @@ bool wxRichTextParagraph::ClearUnusedLines(int lineCount)
return true; 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 * wxRichTextLine
@@ -2937,6 +3131,15 @@ wxRichTextPlainText::wxRichTextPlainText(const wxString& text, wxRichTextObject*
/// Draw the item /// Draw the item
bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int descent, int WXUNUSED(style)) 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(); int offset = GetRange().GetStart();
long len = range.GetLength(); 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 // Test for the optimized situations where all is selected, or none
// is selected. // is selected.
if (GetAttributes().GetFont().Ok()) if (textAttr.GetFont().Ok())
dc.SetFont(GetAttributes().GetFont()); dc.SetFont(textAttr.GetFont());
// (a) All selected. // (a) All selected.
if (selectionRange.GetStart() <= range.GetStart() && selectionRange.GetEnd() >= range.GetEnd()) 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. // (b) None selected.
else if (selectionRange.GetEnd() < range.GetStart() || selectionRange.GetStart() > range.GetEnd()) else if (selectionRange.GetEnd() < range.GetStart() || selectionRange.GetStart() > range.GetEnd())
{ {
// Draw all unselected // Draw all unselected
DrawTabbedString(dc, rect,stringChunk, x, y, false); DrawTabbedString(dc, textAttr, rect, stringChunk, x, y, false);
} }
else 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); wxLogDebug(wxT("Mid(%d, %d"), (int)(r1 - offset), (int)fragmentLen);
wxString stringFragment = m_text.Mid(r1 - offset, 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. // 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); wxLogDebug(wxT("Mid(%d, %d"), (int)(s1 - offset), (int)fragmentLen);
wxString stringFragment = m_text.Mid(s1 - offset, 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 // 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); wxLogDebug(wxT("Mid(%d, %d"), (int)(s2 - offset), (int)fragmentLen);
wxString stringFragment = m_text.Mid(s2 - offset, 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; 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()) if (tab_array.IsEmpty())
{ {
// create a default tab list at 10 mm each. // create a default tab list at 10 mm each.
@@ -3049,7 +3252,7 @@ bool wxRichTextPlainText::DrawTabbedString(wxDC& dc,const wxRect& rect,wxString&
} }
else else
{ {
dc.SetTextForeground(GetAttributes().GetTextColour()); dc.SetTextForeground(attr.GetTextColour());
dc.SetBackgroundMode(wxTRANSPARENT); dc.SetBackgroundMode(wxTRANSPARENT);
} }
@@ -3091,11 +3294,21 @@ bool wxRichTextPlainText::DrawTabbedString(wxDC& dc,const wxRect& rect,wxString&
return true; return true;
} }
/// Lay the item out /// Lay the item out
bool wxRichTextPlainText::Layout(wxDC& dc, const wxRect& WXUNUSED(rect), int WXUNUSED(style)) bool wxRichTextPlainText::Layout(wxDC& dc, const wxRect& WXUNUSED(rect), int WXUNUSED(style))
{ {
if (GetAttributes().GetFont().Ok()) #if wxRICHTEXT_USE_DYNAMIC_STYLES
dc.SetFont(GetAttributes().GetFont()); 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; wxCoord w, h;
dc.GetTextExtent(m_text, & w, & h, & m_descent); dc.GetTextExtent(m_text, & w, & h, & m_descent);
@@ -3119,12 +3332,21 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz
if (!range.IsWithin(GetRange())) if (!range.IsWithin(GetRange()))
return false; 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 // 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 // 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 // formatted text by doing it in chunks according to the line ranges
if (GetAttributes().GetFont().Ok()) if (textAttr.GetFont().Ok())
dc.SetFont(GetAttributes().GetFont()); dc.SetFont(textAttr.GetFont());
int startPos = range.GetStart() - GetRange().GetStart(); int startPos = range.GetStart() - GetRange().GetStart();
long len = range.GetLength(); long len = range.GetLength();
@@ -3134,7 +3356,7 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz
if (stringChunk.Find(wxT('\t')) >= 0) if (stringChunk.Find(wxT('\t')) >= 0)
{ {
// the string has a tab // the string has a tab
wxArrayInt tab_array = GetAttributes().GetTabs(); wxArrayInt tab_array = textAttr.GetTabs();
if (tab_array.IsEmpty()) if (tab_array.IsEmpty())
{ {
// create a default tab list at 10 mm each. // create a default tab list at 10 mm each.
@@ -3322,12 +3544,28 @@ void wxRichTextBuffer::Reset()
} }
/// Submit command to insert the given text /// 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); wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Text"), wxRICHTEXT_INSERT, this, ctrl, false);
action->GetNewParagraphs().AddParagraphs(text); wxTextAttrEx* p = NULL;
if (action->GetNewParagraphs().GetChildCount() == 1) 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->GetNewParagraphs().SetPartialParagraph(true);
action->SetPosition(pos); action->SetPosition(pos);
@@ -3341,12 +3579,25 @@ bool wxRichTextBuffer::InsertTextWithUndo(long pos, const wxString& text, wxRich
} }
/// Submit command to insert the given text /// 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); 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()); wxTextAttrEx attr(GetBasicStyle());
wxRichTextApplyStyle(attr, GetDefaultStyle()); wxRichTextApplyStyle(attr, GetDefaultStyle());
#endif
wxRichTextParagraph* newPara = new wxRichTextParagraph(wxEmptyString, this, & attr); wxRichTextParagraph* newPara = new wxRichTextParagraph(wxEmptyString, this, & attr);
action->GetNewParagraphs().AppendChild(newPara); action->GetNewParagraphs().AppendChild(newPara);
@@ -3354,6 +3605,9 @@ bool wxRichTextBuffer::InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl)
action->GetNewParagraphs().SetPartialParagraph(false); action->GetNewParagraphs().SetPartialParagraph(false);
action->SetPosition(pos); action->SetPosition(pos);
if (p)
newPara->SetAttributes(*p);
// Set the range we'll need to delete in Undo // Set the range we'll need to delete in Undo
action->SetRange(wxRichTextRange(pos, pos)); action->SetRange(wxRichTextRange(pos, pos));
@@ -3363,14 +3617,30 @@ bool wxRichTextBuffer::InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl)
} }
/// Submit command to insert the given image /// 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); 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()); wxTextAttrEx attr(GetBasicStyle());
wxRichTextApplyStyle(attr, GetDefaultStyle()); wxRichTextApplyStyle(attr, GetDefaultStyle());
#endif
wxRichTextParagraph* newPara = new wxRichTextParagraph(this, & attr); wxRichTextParagraph* newPara = new wxRichTextParagraph(this, & attr);
if (p)
newPara->SetAttributes(*p);
wxRichTextImage* imageObject = new wxRichTextImage(imageBlock, newPara); wxRichTextImage* imageObject = new wxRichTextImage(imageBlock, newPara);
newPara->AppendChild(imageObject); newPara->AppendChild(imageObject);
action->GetNewParagraphs().AppendChild(newPara); action->GetNewParagraphs().AppendChild(newPara);
@@ -3388,6 +3658,39 @@ bool wxRichTextBuffer::InsertImageWithUndo(long pos, const wxRichTextImageBlock&
return true; 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 /// Submit command to delete this range
bool wxRichTextBuffer::DeleteRangeWithUndo(const wxRichTextRange& range, long initialCaretPosition, long WXUNUSED(newCaretPositon), wxRichTextCtrl* ctrl) 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(); wxFont font = destStyle.GetFont();
if (style.GetFlags() & wxTEXT_ATTR_FONT_FACE) if (style.GetFlags() & wxTEXT_ATTR_FONT_FACE)
{
destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_FACE);
font.SetFaceName(style.GetFont().GetFaceName()); font.SetFaceName(style.GetFont().GetFaceName());
}
if (style.GetFlags() & wxTEXT_ATTR_FONT_SIZE) if (style.GetFlags() & wxTEXT_ATTR_FONT_SIZE)
{
destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_SIZE);
font.SetPointSize(style.GetFont().GetPointSize()); font.SetPointSize(style.GetFont().GetPointSize());
}
if (style.GetFlags() & wxTEXT_ATTR_FONT_ITALIC) if (style.GetFlags() & wxTEXT_ATTR_FONT_ITALIC)
{
destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_ITALIC);
font.SetStyle(style.GetFont().GetStyle()); font.SetStyle(style.GetFont().GetStyle());
}
if (style.GetFlags() & wxTEXT_ATTR_FONT_WEIGHT) if (style.GetFlags() & wxTEXT_ATTR_FONT_WEIGHT)
{
destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_WEIGHT);
font.SetWeight(style.GetFont().GetWeight()); font.SetWeight(style.GetFont().GetWeight());
}
if (style.GetFlags() & wxTEXT_ATTR_FONT_UNDERLINE) if (style.GetFlags() & wxTEXT_ATTR_FONT_UNDERLINE)
{
destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_UNDERLINE);
font.SetUnderlined(style.GetFont().GetUnderlined()); font.SetUnderlined(style.GetFont().GetUnderlined());
}
if (font != destStyle.GetFont()) if (font != destStyle.GetFont())
{
int oldFlags = destStyle.GetFlags();
destStyle.SetFont(font); destStyle.SetFont(font);
destStyle.SetFlags(oldFlags);
}
} }
if ( style.GetTextColour().Ok() && style.HasTextColour()) if ( style.GetTextColour().Ok() && style.HasTextColour())
@@ -4685,7 +5009,6 @@ bool wxRichTextApplyStyle(wxRichTextAttr& destStyle, const wxTextAttrEx& style)
bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style) bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style)
{ {
// Whole font. Avoiding setting individual attributes if possible, since // Whole font. Avoiding setting individual attributes if possible, since
// it recreates the font each time. // it recreates the font each time.
if ((style.GetFlags() & (wxTEXT_ATTR_FONT)) == (wxTEXT_ATTR_FONT)) if ((style.GetFlags() & (wxTEXT_ATTR_FONT)) == (wxTEXT_ATTR_FONT))
@@ -4698,22 +5021,43 @@ bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style)
wxFont font = destStyle.GetFont(); wxFont font = destStyle.GetFont();
if (style.GetFlags() & wxTEXT_ATTR_FONT_FACE) if (style.GetFlags() & wxTEXT_ATTR_FONT_FACE)
{
destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_FACE);
font.SetFaceName(style.GetFontFaceName()); font.SetFaceName(style.GetFontFaceName());
}
if (style.GetFlags() & wxTEXT_ATTR_FONT_SIZE) if (style.GetFlags() & wxTEXT_ATTR_FONT_SIZE)
{
destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_SIZE);
font.SetPointSize(style.GetFontSize()); font.SetPointSize(style.GetFontSize());
}
if (style.GetFlags() & wxTEXT_ATTR_FONT_ITALIC) if (style.GetFlags() & wxTEXT_ATTR_FONT_ITALIC)
{
destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_ITALIC);
font.SetStyle(style.GetFontStyle()); font.SetStyle(style.GetFontStyle());
}
if (style.GetFlags() & wxTEXT_ATTR_FONT_WEIGHT) if (style.GetFlags() & wxTEXT_ATTR_FONT_WEIGHT)
{
destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_WEIGHT);
font.SetWeight(style.GetFontWeight()); font.SetWeight(style.GetFontWeight());
}
if (style.GetFlags() & wxTEXT_ATTR_FONT_UNDERLINE) if (style.GetFlags() & wxTEXT_ATTR_FONT_UNDERLINE)
{
destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_UNDERLINE);
font.SetUnderlined(style.GetFontUnderlined()); font.SetUnderlined(style.GetFontUnderlined());
}
if (font != destStyle.GetFont()) if (font != destStyle.GetFont())
{
int oldFlags = destStyle.GetFlags();
destStyle.SetFont(font); destStyle.SetFont(font);
destStyle.SetFlags(oldFlags);
}
} }
if ( style.GetTextColour().Ok() && style.HasTextColour()) if ( style.GetTextColour().Ok() && style.HasTextColour())
@@ -4867,6 +5211,33 @@ wxRichTextAttr::operator wxTextAttrEx () const
return attr; 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 // Copy to a wxTextAttr
void wxRichTextAttr::CopyTo(wxTextAttrEx& attr) const void wxRichTextAttr::CopyTo(wxTextAttrEx& attr) const
{ {
@@ -4877,7 +5248,6 @@ void wxRichTextAttr::CopyTo(wxTextAttrEx& attr) const
attr.SetLeftIndent(GetLeftIndent(), GetLeftSubIndent()); attr.SetLeftIndent(GetLeftIndent(), GetLeftSubIndent());
attr.SetRightIndent(GetRightIndent()); attr.SetRightIndent(GetRightIndent());
attr.SetFont(CreateFont()); attr.SetFont(CreateFont());
attr.SetFlags(GetFlags()); // Important: set after SetFont, since SetFont sets flags
attr.SetParagraphSpacingAfter(m_paragraphSpacingAfter); attr.SetParagraphSpacingAfter(m_paragraphSpacingAfter);
attr.SetParagraphSpacingBefore(m_paragraphSpacingBefore); attr.SetParagraphSpacingBefore(m_paragraphSpacingBefore);
@@ -4888,6 +5258,7 @@ void wxRichTextAttr::CopyTo(wxTextAttrEx& attr) const
attr.SetCharacterStyleName(m_characterStyleName); attr.SetCharacterStyleName(m_characterStyleName);
attr.SetParagraphStyleName(m_paragraphStyleName); attr.SetParagraphStyleName(m_paragraphStyleName);
attr.SetFlags(GetFlags()); // Important: set after SetFont and others, since they set flags
} }
// Create font from font attributes. // Create font from font attributes.

View File

@@ -22,11 +22,8 @@
#include "wx/richtext/richtextstyles.h" #include "wx/richtext/richtextstyles.h"
#ifndef WX_PRECOMP #ifndef WX_PRECOMP
#include "wx/wx.h"
#include "wx/settings.h" #include "wx/settings.h"
#include "wx/menu.h"
#include "wx/intl.h"
#include "wx/log.h"
#include "wx/stopwatch.h"
#endif #endif
#include "wx/textfile.h" #include "wx/textfile.h"
@@ -145,10 +142,13 @@ bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxString& va
attributes.SetBackgroundColour(*wxWHITE); attributes.SetBackgroundColour(*wxWHITE);
attributes.SetAlignment(wxTEXT_ALIGNMENT_LEFT); attributes.SetAlignment(wxTEXT_ALIGNMENT_LEFT);
attributes.SetFlags(wxTEXT_ATTR_ALL); attributes.SetFlags(wxTEXT_ATTR_ALL);
SetDefaultStyle(attributes);
SetBasicStyle(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); SetBackgroundColour(*wxWHITE);
SetBackgroundStyle(wxBG_STYLE_CUSTOM); SetBackgroundStyle(wxBG_STYLE_CUSTOM);
@@ -466,7 +466,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
DeleteSelectedContent(& newPos); DeleteSelectedContent(& newPos);
GetBuffer().InsertNewlineWithUndo(newPos+1, this); GetBuffer().InsertNewlineWithUndo(newPos+1, this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE);
wxRichTextEvent cmdEvent( wxRichTextEvent cmdEvent(
wxEVT_COMMAND_RICHTEXT_RETURN, wxEVT_COMMAND_RICHTEXT_RETURN,
@@ -545,7 +545,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
DeleteSelectedContent(& newPos); DeleteSelectedContent(& newPos);
wxString str = (wxChar) event.GetKeyCode(); wxString str = (wxChar) event.GetKeyCode();
GetBuffer().InsertTextWithUndo(newPos+1, str, this); GetBuffer().InsertTextWithUndo(newPos+1, str, this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE);
EndBatchUndo(); EndBatchUndo();
@@ -1744,6 +1744,7 @@ void wxRichTextCtrl::WriteText(const wxString& value)
void wxRichTextCtrl::DoWriteText(const wxString& value, bool WXUNUSED(selectionOnly)) void wxRichTextCtrl::DoWriteText(const wxString& value, bool WXUNUSED(selectionOnly))
{ {
wxString valueDos = wxTextFile::Translate(value, wxTextFileType_Unix); wxString valueDos = wxTextFile::Translate(value, wxTextFileType_Unix);
GetBuffer().InsertTextWithUndo(m_caretPosition+1, valueDos, this); GetBuffer().InsertTextWithUndo(m_caretPosition+1, valueDos, this);
} }
@@ -1811,7 +1812,7 @@ void wxRichTextCtrl::Copy()
{ {
if (CanCopy()) if (CanCopy())
{ {
wxRichTextRange range = GetSelectionRange(); wxRichTextRange range = GetInternalSelectionRange();
GetBuffer().CopyToClipboard(range); GetBuffer().CopyToClipboard(range);
} }
} }
@@ -1820,7 +1821,7 @@ void wxRichTextCtrl::Cut()
{ {
if (CanCut()) if (CanCut())
{ {
wxRichTextRange range = GetSelectionRange(); wxRichTextRange range = GetInternalSelectionRange();
GetBuffer().CopyToClipboard(range); GetBuffer().CopyToClipboard(range);
DeleteSelectedContent(); DeleteSelectedContent();
@@ -2258,7 +2259,7 @@ const wxTextAttr& wxRichTextCtrl::GetDefaultStyle() const
bool wxRichTextCtrl::GetStyle(long position, wxTextAttr& style) bool wxRichTextCtrl::GetStyle(long position, wxTextAttr& style)
{ {
wxTextAttrEx attr; wxTextAttrEx attr(style);
if (GetBuffer().GetStyle(position, attr)) if (GetBuffer().GetStyle(position, attr))
{ {
style = attr; style = attr;
@@ -2278,6 +2279,30 @@ bool wxRichTextCtrl::GetStyle(long position, wxRichTextAttr& style)
return GetBuffer().GetStyle(position, 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 /// Set font, and also the buffer attributes
bool wxRichTextCtrl::SetFont(const wxFont& font) bool wxRichTextCtrl::SetFont(const wxFont& font)
{ {
@@ -2290,7 +2315,15 @@ bool wxRichTextCtrl::SetFont(const wxFont& font)
wxTextAttrEx attr = GetBuffer().GetAttributes(); wxTextAttrEx attr = GetBuffer().GetAttributes();
attr.SetFont(font); attr.SetFont(font);
GetBuffer().SetBasicStyle(attr); 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); GetBuffer().SetDefaultStyle(attr);
#endif
GetBuffer().Invalidate(wxRICHTEXT_ALL);
Refresh(false);
return true; return true;
} }
@@ -2508,8 +2541,8 @@ bool wxRichTextCtrl::IsSelectionUnderlined()
// to see what the effect would be if we started typing. // to see what the effect would be if we started typing.
wxRichTextAttr attr; wxRichTextAttr attr;
attr.SetFlags(wxTEXT_ATTR_FONT_UNDERLINE); attr.SetFlags(wxTEXT_ATTR_FONT_UNDERLINE);
long pos = GetAdjustedCaretPosition(GetCaretPosition()); long pos = GetAdjustedCaretPosition(GetCaretPosition());
if (GetStyle(pos, attr)) if (GetStyle(pos, attr))
{ {
if (IsDefaultStyleShowing()) if (IsDefaultStyleShowing())
@@ -2618,6 +2651,24 @@ void wxRichTextCtrl::ApplyStyle(wxRichTextStyleDefinition* def)
SetAndShowDefaultStyle(attr); 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 /// Sets the default style to the style under the cursor
bool wxRichTextCtrl::SetDefaultStyleToCursorStyle() bool wxRichTextCtrl::SetDefaultStyleToCursorStyle()
{ {
@@ -2627,7 +2678,11 @@ bool wxRichTextCtrl::SetDefaultStyleToCursorStyle()
// If at the start of a paragraph, use the next position. // If at the start of a paragraph, use the next position.
long pos = GetAdjustedCaretPosition(GetCaretPosition()); long pos = GetAdjustedCaretPosition(GetCaretPosition());
#if wxRICHTEXT_USE_DYNAMIC_STYLES
if (GetUncombinedStyle(pos, attr))
#else
if (GetStyle(pos, attr)) if (GetStyle(pos, attr))
#endif
{ {
SetDefaultStyle(attr); SetDefaultStyle(attr);
return true; return true;

View File

@@ -21,8 +21,7 @@
#include "wx/richtext/richtextstyles.h" #include "wx/richtext/richtextstyles.h"
#ifndef WX_PRECOMP #ifndef WX_PRECOMP
#include "wx/dcclient.h" #include "wx/wx.h"
#include "wx/module.h"
#endif #endif
#include "wx/filename.h" #include "wx/filename.h"
@@ -35,6 +34,38 @@ IMPLEMENT_CLASS(wxRichTextStyleDefinition, wxObject)
IMPLEMENT_CLASS(wxRichTextCharacterStyleDefinition, wxRichTextStyleDefinition) IMPLEMENT_CLASS(wxRichTextCharacterStyleDefinition, wxRichTextStyleDefinition)
IMPLEMENT_CLASS(wxRichTextParagraphStyleDefinition, 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 * The style manager
*/ */
@@ -89,6 +120,48 @@ void wxRichTextStyleSheet::DeleteStyles()
WX_CLEAR_LIST(wxList, m_paragraphStyleDefinitions); 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 #if wxUSE_HTML
/*! /*!
* wxRichTextStyleListBox class declaration * wxRichTextStyleListBox class declaration
@@ -316,8 +389,10 @@ void wxRichTextStyleListBox::OnIdle(wxIdleEvent& event)
{ {
if (CanAutoSetSelection() && GetRichTextCtrl()) if (CanAutoSetSelection() && GetRichTextCtrl())
{ {
wxRichTextParagraph* para = GetRichTextCtrl()->GetBuffer().GetParagraphAtPosition(GetRichTextCtrl()->GetCaretPosition()); int adjustedCaretPos = GetRichTextCtrl()->GetAdjustedCaretPosition(GetRichTextCtrl()->GetCaretPosition());
wxRichTextObject* obj = GetRichTextCtrl()->GetBuffer().GetLeafObjectAtPosition(GetRichTextCtrl()->GetCaretPosition());
wxRichTextParagraph* para = GetRichTextCtrl()->GetBuffer().GetParagraphAtPosition(adjustedCaretPos);
wxRichTextObject* obj = GetRichTextCtrl()->GetBuffer().GetLeafObjectAtPosition(adjustedCaretPos);
wxString styleName; wxString styleName;
@@ -483,8 +558,10 @@ void wxRichTextStyleComboCtrl::OnIdle(wxIdleEvent& event)
{ {
if (GetRichTextCtrl() && !IsPopupShown()) if (GetRichTextCtrl() && !IsPopupShown())
{ {
wxRichTextParagraph* para = GetRichTextCtrl()->GetBuffer().GetParagraphAtPosition(GetRichTextCtrl()->GetCaretPosition()); int adjustedCaretPos = GetRichTextCtrl()->GetAdjustedCaretPosition(GetRichTextCtrl()->GetCaretPosition());
wxRichTextObject* obj = GetRichTextCtrl()->GetBuffer().GetLeafObjectAtPosition(GetRichTextCtrl()->GetCaretPosition());
wxRichTextParagraph* para = GetRichTextCtrl()->GetBuffer().GetParagraphAtPosition(adjustedCaretPos);
wxRichTextObject* obj = GetRichTextCtrl()->GetBuffer().GetLeafObjectAtPosition(adjustedCaretPos);
wxString styleName; wxString styleName;