Fixed several style, paste and undo bugs
Added a reload function to the sample for quickly restoring original text git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@51740 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -166,6 +166,8 @@ public:
|
|||||||
void OnDemoteList(wxCommandEvent& event);
|
void OnDemoteList(wxCommandEvent& event);
|
||||||
void OnClearList(wxCommandEvent& event);
|
void OnClearList(wxCommandEvent& event);
|
||||||
|
|
||||||
|
void OnReload(wxCommandEvent& event);
|
||||||
|
|
||||||
void OnViewHTML(wxCommandEvent& event);
|
void OnViewHTML(wxCommandEvent& event);
|
||||||
|
|
||||||
void OnSwitchStyleSheets(wxCommandEvent& event);
|
void OnSwitchStyleSheets(wxCommandEvent& event);
|
||||||
@@ -182,6 +184,9 @@ public:
|
|||||||
// 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);
|
||||||
|
|
||||||
|
// Write text
|
||||||
|
void WriteInitialText();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// any class wishing to process wxWidgets events must use this macro
|
// any class wishing to process wxWidgets events must use this macro
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
@@ -207,6 +212,8 @@ enum
|
|||||||
ID_FORMAT_PARAGRAPH,
|
ID_FORMAT_PARAGRAPH,
|
||||||
ID_FORMAT_CONTENT,
|
ID_FORMAT_CONTENT,
|
||||||
|
|
||||||
|
ID_RELOAD,
|
||||||
|
|
||||||
ID_INSERT_SYMBOL,
|
ID_INSERT_SYMBOL,
|
||||||
ID_INSERT_URL,
|
ID_INSERT_URL,
|
||||||
|
|
||||||
@@ -292,6 +299,8 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
|||||||
EVT_MENU(ID_FORMAT_PARAGRAPH_SPACING_MORE, MyFrame::OnParagraphSpacingMore)
|
EVT_MENU(ID_FORMAT_PARAGRAPH_SPACING_MORE, MyFrame::OnParagraphSpacingMore)
|
||||||
EVT_MENU(ID_FORMAT_PARAGRAPH_SPACING_LESS, MyFrame::OnParagraphSpacingLess)
|
EVT_MENU(ID_FORMAT_PARAGRAPH_SPACING_LESS, MyFrame::OnParagraphSpacingLess)
|
||||||
|
|
||||||
|
EVT_MENU(ID_RELOAD, MyFrame::OnReload)
|
||||||
|
|
||||||
EVT_MENU(ID_INSERT_SYMBOL, MyFrame::OnInsertSymbol)
|
EVT_MENU(ID_INSERT_SYMBOL, MyFrame::OnInsertSymbol)
|
||||||
EVT_MENU(ID_INSERT_URL, MyFrame::OnInsertURL)
|
EVT_MENU(ID_INSERT_URL, MyFrame::OnInsertURL)
|
||||||
|
|
||||||
@@ -564,6 +573,8 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
|
|||||||
fileMenu->Append(wxID_SAVE, _T("&Save\tCtrl+S"), _T("Save a file"));
|
fileMenu->Append(wxID_SAVE, _T("&Save\tCtrl+S"), _T("Save a file"));
|
||||||
fileMenu->Append(wxID_SAVEAS, _T("&Save As...\tF12"), _T("Save to a new file"));
|
fileMenu->Append(wxID_SAVEAS, _T("&Save As...\tF12"), _T("Save to a new file"));
|
||||||
fileMenu->AppendSeparator();
|
fileMenu->AppendSeparator();
|
||||||
|
fileMenu->Append(ID_RELOAD, _T("&Reload Text\tF2"), _T("Reload the initial text"));
|
||||||
|
fileMenu->AppendSeparator();
|
||||||
fileMenu->Append(ID_PAGE_SETUP, _T("Page Set&up..."), _T("Page setup"));
|
fileMenu->Append(ID_PAGE_SETUP, _T("Page Set&up..."), _T("Page setup"));
|
||||||
fileMenu->Append(ID_PRINT, _T("&Print...\tCtrl+P"), _T("Print"));
|
fileMenu->Append(ID_PRINT, _T("&Print...\tCtrl+P"), _T("Print"));
|
||||||
fileMenu->Append(ID_PREVIEW, _T("Print Pre&view"), _T("Print preview"));
|
fileMenu->Append(ID_PREVIEW, _T("Print Pre&view"), _T("Print preview"));
|
||||||
@@ -717,8 +728,16 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
|
|||||||
styleListCtrl->SetRichTextCtrl(m_richTextCtrl);
|
styleListCtrl->SetRichTextCtrl(m_richTextCtrl);
|
||||||
styleListCtrl->UpdateStyles();
|
styleListCtrl->UpdateStyles();
|
||||||
|
|
||||||
|
WriteInitialText();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write text
|
||||||
|
void MyFrame::WriteInitialText()
|
||||||
|
{
|
||||||
wxRichTextCtrl& r = *m_richTextCtrl;
|
wxRichTextCtrl& r = *m_richTextCtrl;
|
||||||
|
|
||||||
|
r.SetDefaultStyle(wxRichTextAttr());
|
||||||
|
|
||||||
r.BeginSuppressUndo();
|
r.BeginSuppressUndo();
|
||||||
|
|
||||||
r.BeginParagraphSpacing(0, 20);
|
r.BeginParagraphSpacing(0, 20);
|
||||||
@@ -730,9 +749,8 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
|
|||||||
|
|
||||||
wxString lineBreak = (wxChar) 29;
|
wxString lineBreak = (wxChar) 29;
|
||||||
|
|
||||||
r.WriteText(wxString(wxT("Welcome to wxRichTextCtrl, a wxWidgets control")) + lineBreak + wxT("for editing and presenting styled text and images"));
|
r.WriteText(wxString(wxT("Welcome to wxRichTextCtrl, a wxWidgets control")) + lineBreak + wxT("for editing and presenting styled text and images\n"));
|
||||||
r.EndFontSize();
|
r.EndFontSize();
|
||||||
r.Newline();
|
|
||||||
|
|
||||||
r.BeginItalic();
|
r.BeginItalic();
|
||||||
r.WriteText(wxT("by Julian Smart"));
|
r.WriteText(wxT("by Julian Smart"));
|
||||||
@@ -743,10 +761,10 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
|
|||||||
|
|
||||||
r.WriteImage(wxBitmap(zebra_xpm));
|
r.WriteImage(wxBitmap(zebra_xpm));
|
||||||
|
|
||||||
r.EndAlignment();
|
r.Newline();
|
||||||
|
r.Newline();
|
||||||
|
|
||||||
r.Newline();
|
r.EndAlignment();
|
||||||
r.Newline();
|
|
||||||
|
|
||||||
r.WriteText(wxT("What can you do with this thing? "));
|
r.WriteText(wxT("What can you do with this thing? "));
|
||||||
|
|
||||||
@@ -781,57 +799,55 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
|
|||||||
|
|
||||||
r.WriteText(wxT(" Next we'll show an indented paragraph."));
|
r.WriteText(wxT(" Next we'll show an indented paragraph."));
|
||||||
|
|
||||||
|
r.Newline();
|
||||||
|
|
||||||
r.BeginLeftIndent(60);
|
r.BeginLeftIndent(60);
|
||||||
r.Newline();
|
|
||||||
|
|
||||||
r.WriteText(wxT("It was in January, the most down-trodden month of an Edinburgh winter. An attractive woman came into the cafe, which is nothing remarkable."));
|
r.WriteText(wxT("It was in January, the most down-trodden month of an Edinburgh winter. An attractive woman came into the cafe, which is nothing remarkable."));
|
||||||
r.EndLeftIndent();
|
|
||||||
|
|
||||||
r.Newline();
|
r.Newline();
|
||||||
|
|
||||||
|
r.EndLeftIndent();
|
||||||
|
|
||||||
r.WriteText(wxT("Next, we'll show a first-line indent, achieved using BeginLeftIndent(100, -40)."));
|
r.WriteText(wxT("Next, we'll show a first-line indent, achieved using BeginLeftIndent(100, -40)."));
|
||||||
|
|
||||||
r.BeginLeftIndent(100, -40);
|
|
||||||
r.Newline();
|
r.Newline();
|
||||||
|
|
||||||
|
r.BeginLeftIndent(100, -40);
|
||||||
|
|
||||||
r.WriteText(wxT("It was in January, the most down-trodden month of an Edinburgh winter. An attractive woman came into the cafe, which is nothing remarkable."));
|
r.WriteText(wxT("It was in January, the most down-trodden month of an Edinburgh winter. An attractive woman came into the cafe, which is nothing remarkable."));
|
||||||
|
r.Newline();
|
||||||
|
|
||||||
r.EndLeftIndent();
|
r.EndLeftIndent();
|
||||||
|
|
||||||
r.Newline();
|
|
||||||
|
|
||||||
r.WriteText(wxT("Numbered bullets are possible, again using subindents:"));
|
r.WriteText(wxT("Numbered bullets are possible, again using subindents:"));
|
||||||
|
r.Newline();
|
||||||
|
|
||||||
r.BeginNumberedBullet(1, 100, 60);
|
r.BeginNumberedBullet(1, 100, 60);
|
||||||
r.Newline();
|
|
||||||
|
|
||||||
r.WriteText(wxT("This is my first item. Note that wxRichTextCtrl can apply numbering and bullets automatically based on list styles, but this list is formatted explicitly by setting indents."));
|
r.WriteText(wxT("This is my first item. Note that wxRichTextCtrl can apply numbering and bullets automatically based on list styles, but this list is formatted explicitly by setting indents."));
|
||||||
|
r.Newline();
|
||||||
r.EndNumberedBullet();
|
r.EndNumberedBullet();
|
||||||
|
|
||||||
r.BeginNumberedBullet(2, 100, 60);
|
r.BeginNumberedBullet(2, 100, 60);
|
||||||
r.Newline();
|
|
||||||
|
|
||||||
r.WriteText(wxT("This is my second item."));
|
r.WriteText(wxT("This is my second item."));
|
||||||
|
r.Newline();
|
||||||
r.EndNumberedBullet();
|
r.EndNumberedBullet();
|
||||||
|
|
||||||
r.Newline();
|
|
||||||
|
|
||||||
r.WriteText(wxT("The following paragraph is right-indented:"));
|
r.WriteText(wxT("The following paragraph is right-indented:"));
|
||||||
|
r.Newline();
|
||||||
|
|
||||||
r.BeginRightIndent(200);
|
r.BeginRightIndent(200);
|
||||||
r.Newline();
|
|
||||||
|
|
||||||
r.WriteText(wxT("It was in January, the most down-trodden month of an Edinburgh winter. An attractive woman came into the cafe, which is nothing remarkable."));
|
r.WriteText(wxT("It was in January, the most down-trodden month of an Edinburgh winter. An attractive woman came into the cafe, which is nothing remarkable."));
|
||||||
r.EndRightIndent();
|
|
||||||
|
|
||||||
r.Newline();
|
r.Newline();
|
||||||
|
|
||||||
|
r.EndRightIndent();
|
||||||
|
|
||||||
r.WriteText(wxT("The following paragraph is right-aligned with 1.5 line spacing:"));
|
r.WriteText(wxT("The following paragraph is right-aligned with 1.5 line spacing:"));
|
||||||
|
r.Newline();
|
||||||
|
|
||||||
r.BeginAlignment(wxTEXT_ALIGNMENT_RIGHT);
|
r.BeginAlignment(wxTEXT_ALIGNMENT_RIGHT);
|
||||||
r.BeginLineSpacing(wxTEXT_ATTR_LINE_SPACING_HALF);
|
r.BeginLineSpacing(wxTEXT_ATTR_LINE_SPACING_HALF);
|
||||||
r.Newline();
|
|
||||||
|
|
||||||
r.WriteText(wxT("It was in January, the most down-trodden month of an Edinburgh winter. An attractive woman came into the cafe, which is nothing remarkable."));
|
r.WriteText(wxT("It was in January, the most down-trodden month of an Edinburgh winter. An attractive woman came into the cafe, which is nothing remarkable."));
|
||||||
|
r.Newline();
|
||||||
r.EndLineSpacing();
|
r.EndLineSpacing();
|
||||||
r.EndAlignment();
|
r.EndAlignment();
|
||||||
|
|
||||||
@@ -840,53 +856,51 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
|
|||||||
tabs.Add(600);
|
tabs.Add(600);
|
||||||
tabs.Add(800);
|
tabs.Add(800);
|
||||||
tabs.Add(1000);
|
tabs.Add(1000);
|
||||||
wxRichTextAttr attr;
|
wxTextAttrEx attr;
|
||||||
attr.SetFlags(wxTEXT_ATTR_TABS);
|
attr.SetFlags(wxTEXT_ATTR_TABS);
|
||||||
attr.SetTabs(tabs);
|
attr.SetTabs(tabs);
|
||||||
r.SetDefaultStyle(attr);
|
r.SetDefaultStyle(attr);
|
||||||
|
|
||||||
r.Newline();
|
|
||||||
r.WriteText(wxT("This line contains tabs:\tFirst tab\tSecond tab\tThird tab"));
|
r.WriteText(wxT("This line contains tabs:\tFirst tab\tSecond tab\tThird tab"));
|
||||||
|
|
||||||
r.Newline();
|
r.Newline();
|
||||||
|
|
||||||
r.WriteText(wxT("Other notable features of wxRichTextCtrl include:"));
|
r.WriteText(wxT("Other notable features of wxRichTextCtrl include:"));
|
||||||
|
r.Newline();
|
||||||
|
|
||||||
r.BeginSymbolBullet(wxT('*'), 100, 60);
|
r.BeginSymbolBullet(wxT('*'), 100, 60);
|
||||||
r.Newline();
|
|
||||||
r.WriteText(wxT("Compatibility with wxTextCtrl API"));
|
r.WriteText(wxT("Compatibility with wxTextCtrl API"));
|
||||||
|
r.Newline();
|
||||||
r.EndSymbolBullet();
|
r.EndSymbolBullet();
|
||||||
|
|
||||||
r.BeginSymbolBullet(wxT('*'), 100, 60);
|
r.BeginSymbolBullet(wxT('*'), 100, 60);
|
||||||
r.Newline();
|
|
||||||
r.WriteText(wxT("Easy stack-based BeginXXX()...EndXXX() style setting in addition to SetStyle()"));
|
r.WriteText(wxT("Easy stack-based BeginXXX()...EndXXX() style setting in addition to SetStyle()"));
|
||||||
|
r.Newline();
|
||||||
r.EndSymbolBullet();
|
r.EndSymbolBullet();
|
||||||
|
|
||||||
r.BeginSymbolBullet(wxT('*'), 100, 60);
|
r.BeginSymbolBullet(wxT('*'), 100, 60);
|
||||||
r.Newline();
|
|
||||||
r.WriteText(wxT("XML loading and saving"));
|
r.WriteText(wxT("XML loading and saving"));
|
||||||
|
r.Newline();
|
||||||
r.EndSymbolBullet();
|
r.EndSymbolBullet();
|
||||||
|
|
||||||
r.BeginSymbolBullet(wxT('*'), 100, 60);
|
r.BeginSymbolBullet(wxT('*'), 100, 60);
|
||||||
r.Newline();
|
|
||||||
r.WriteText(wxT("Undo/Redo, with batching option and Undo suppressing"));
|
r.WriteText(wxT("Undo/Redo, with batching option and Undo suppressing"));
|
||||||
|
r.Newline();
|
||||||
r.EndSymbolBullet();
|
r.EndSymbolBullet();
|
||||||
|
|
||||||
r.BeginSymbolBullet(wxT('*'), 100, 60);
|
r.BeginSymbolBullet(wxT('*'), 100, 60);
|
||||||
r.Newline();
|
|
||||||
r.WriteText(wxT("Clipboard copy and paste"));
|
r.WriteText(wxT("Clipboard copy and paste"));
|
||||||
|
r.Newline();
|
||||||
r.EndSymbolBullet();
|
r.EndSymbolBullet();
|
||||||
|
|
||||||
r.BeginSymbolBullet(wxT('*'), 100, 60);
|
r.BeginSymbolBullet(wxT('*'), 100, 60);
|
||||||
r.Newline();
|
|
||||||
r.WriteText(wxT("wxRichTextStyleSheet with named character and paragraph styles, and control for applying named styles"));
|
r.WriteText(wxT("wxRichTextStyleSheet with named character and paragraph styles, and control for applying named styles"));
|
||||||
|
r.Newline();
|
||||||
r.EndSymbolBullet();
|
r.EndSymbolBullet();
|
||||||
|
|
||||||
r.BeginSymbolBullet(wxT('*'), 100, 60);
|
r.BeginSymbolBullet(wxT('*'), 100, 60);
|
||||||
r.Newline();
|
|
||||||
r.WriteText(wxT("A design that can easily be extended to other content types, ultimately with text boxes, tables, controls, and so on"));
|
r.WriteText(wxT("A design that can easily be extended to other content types, ultimately with text boxes, tables, controls, and so on"));
|
||||||
r.EndSymbolBullet();
|
|
||||||
|
|
||||||
r.Newline();
|
r.Newline();
|
||||||
|
r.EndSymbolBullet();
|
||||||
|
|
||||||
// Make a style suitable for showing a URL
|
// Make a style suitable for showing a URL
|
||||||
wxRichTextAttr urlStyle;
|
wxRichTextAttr urlStyle;
|
||||||
@@ -903,14 +917,13 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
|
|||||||
|
|
||||||
r.Newline();
|
r.Newline();
|
||||||
|
|
||||||
r.WriteText(wxT("Note: this sample content was generated programmatically from within the MyFrame constructor in the demo. The images were loaded from inline XPMs. Enjoy wxRichTextCtrl!"));
|
r.WriteText(wxT("Note: this sample content was generated programmatically from within the MyFrame constructor in the demo. The images were loaded from inline XPMs. Enjoy wxRichTextCtrl!\n"));
|
||||||
|
|
||||||
r.EndParagraphSpacing();
|
r.EndParagraphSpacing();
|
||||||
|
|
||||||
r.EndSuppressUndo();
|
r.EndSuppressUndo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// event handlers
|
// event handlers
|
||||||
|
|
||||||
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
|
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
|
||||||
@@ -1313,6 +1326,12 @@ void MyFrame::OnParagraphSpacingLess(wxCommandEvent& WXUNUSED(event))
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyFrame::OnReload(wxCommandEvent& WXUNUSED(event))
|
||||||
|
{
|
||||||
|
m_richTextCtrl->Clear();
|
||||||
|
WriteInitialText();
|
||||||
|
}
|
||||||
|
|
||||||
void MyFrame::OnViewHTML(wxCommandEvent& WXUNUSED(event))
|
void MyFrame::OnViewHTML(wxCommandEvent& WXUNUSED(event))
|
||||||
{
|
{
|
||||||
wxDialog dialog(this, wxID_ANY, _("HTML"), wxDefaultPosition, wxSize(500, 400), wxDEFAULT_DIALOG_STYLE);
|
wxDialog dialog(this, wxID_ANY, _("HTML"), wxDefaultPosition, wxSize(500, 400), wxDEFAULT_DIALOG_STYLE);
|
||||||
|
@@ -1007,15 +1007,18 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraphs(const wxString& text
|
|||||||
wxChar ch = text[i];
|
wxChar ch = text[i];
|
||||||
if (ch == wxT('\n') || ch == wxT('\r'))
|
if (ch == wxT('\n') || ch == wxT('\r'))
|
||||||
{
|
{
|
||||||
wxRichTextPlainText* plainText = (wxRichTextPlainText*) para->GetChildren().GetFirst()->GetData();
|
if (i != (len-1))
|
||||||
plainText->SetText(line);
|
{
|
||||||
|
wxRichTextPlainText* plainText = (wxRichTextPlainText*) para->GetChildren().GetFirst()->GetData();
|
||||||
|
plainText->SetText(line);
|
||||||
|
|
||||||
para = new wxRichTextParagraph(wxEmptyString, this, pStyle, cStyle);
|
para = new wxRichTextParagraph(wxEmptyString, this, pStyle, cStyle);
|
||||||
|
|
||||||
AppendChild(para);
|
AppendChild(para);
|
||||||
|
|
||||||
lastPara = para;
|
lastPara = para;
|
||||||
line = wxEmptyString;
|
line = wxEmptyString;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
line += ch;
|
line += ch;
|
||||||
@@ -1073,6 +1076,8 @@ bool wxRichTextParagraphLayoutBox::InsertFragment(long position, wxRichTextParag
|
|||||||
wxRichTextParagraph* para = GetParagraphAtPosition(position);
|
wxRichTextParagraph* para = GetParagraphAtPosition(position);
|
||||||
if (para)
|
if (para)
|
||||||
{
|
{
|
||||||
|
wxTextAttrEx originalAttr = para->GetAttributes();
|
||||||
|
|
||||||
wxRichTextObjectList::compatibility_iterator node = m_children.Find(para);
|
wxRichTextObjectList::compatibility_iterator node = m_children.Find(para);
|
||||||
|
|
||||||
// Now split at this position, returning the object to insert the new
|
// Now split at this position, returning the object to insert the new
|
||||||
@@ -1093,11 +1098,6 @@ bool wxRichTextParagraphLayoutBox::InsertFragment(long position, wxRichTextParag
|
|||||||
wxRichTextParagraph* firstPara = wxDynamicCast(firstParaNode->GetData(), wxRichTextParagraph);
|
wxRichTextParagraph* firstPara = wxDynamicCast(firstParaNode->GetData(), wxRichTextParagraph);
|
||||||
wxASSERT (firstPara != NULL);
|
wxASSERT (firstPara != NULL);
|
||||||
|
|
||||||
// Apply the new paragraph attributes to the existing paragraph
|
|
||||||
wxTextAttr attr(para->GetAttributes());
|
|
||||||
wxRichTextApplyStyle(attr, firstPara->GetAttributes());
|
|
||||||
para->SetAttributes(attr);
|
|
||||||
|
|
||||||
wxRichTextObjectList::compatibility_iterator objectNode = firstPara->GetChildren().GetFirst();
|
wxRichTextObjectList::compatibility_iterator objectNode = firstPara->GetChildren().GetFirst();
|
||||||
while (objectNode)
|
while (objectNode)
|
||||||
{
|
{
|
||||||
@@ -1145,13 +1145,27 @@ bool wxRichTextParagraphLayoutBox::InsertFragment(long position, wxRichTextParag
|
|||||||
wxRichTextParagraph* firstPara = wxDynamicCast(firstParaNode->GetData(), wxRichTextParagraph);
|
wxRichTextParagraph* firstPara = wxDynamicCast(firstParaNode->GetData(), wxRichTextParagraph);
|
||||||
wxASSERT(firstPara != NULL);
|
wxASSERT(firstPara != NULL);
|
||||||
|
|
||||||
|
para->SetAttributes(firstPara->GetAttributes());
|
||||||
|
|
||||||
|
// Save empty paragraph attributes for appending later
|
||||||
|
// These are character attributes deliberately set for a new paragraph. Without this,
|
||||||
|
// we couldn't pass default attributes when appending a new paragraph.
|
||||||
|
wxTextAttrEx emptyParagraphAttributes;
|
||||||
|
|
||||||
wxRichTextObjectList::compatibility_iterator objectNode = firstPara->GetChildren().GetFirst();
|
wxRichTextObjectList::compatibility_iterator objectNode = firstPara->GetChildren().GetFirst();
|
||||||
|
|
||||||
|
if (objectNode && firstPara->GetChildren().GetCount() == 1 && objectNode->GetData()->IsEmpty())
|
||||||
|
emptyParagraphAttributes = objectNode->GetData()->GetAttributes();
|
||||||
|
|
||||||
while (objectNode)
|
while (objectNode)
|
||||||
{
|
{
|
||||||
wxRichTextObject* newObj = objectNode->GetData()->Clone();
|
if (!objectNode->GetData()->IsEmpty())
|
||||||
|
{
|
||||||
|
wxRichTextObject* newObj = objectNode->GetData()->Clone();
|
||||||
|
|
||||||
// Append
|
// Append
|
||||||
para->AppendChild(newObj);
|
para->AppendChild(newObj);
|
||||||
|
}
|
||||||
|
|
||||||
objectNode = objectNode->GetNext();
|
objectNode = objectNode->GetNext();
|
||||||
}
|
}
|
||||||
@@ -1165,22 +1179,10 @@ bool wxRichTextParagraphLayoutBox::InsertFragment(long position, wxRichTextParag
|
|||||||
wxRichTextObjectList::compatibility_iterator i = fragment.GetChildren().GetFirst()->GetNext();
|
wxRichTextObjectList::compatibility_iterator i = fragment.GetChildren().GetFirst()->GetNext();
|
||||||
wxRichTextParagraph* finalPara = para;
|
wxRichTextParagraph* finalPara = para;
|
||||||
|
|
||||||
|
bool needExtraPara = (!i || !fragment.GetPartialParagraph());
|
||||||
|
|
||||||
// If there was only one paragraph, we need to insert a new one.
|
// If there was only one paragraph, we need to insert a new one.
|
||||||
if (!i)
|
while (i)
|
||||||
{
|
|
||||||
finalPara = new wxRichTextParagraph;
|
|
||||||
|
|
||||||
// TODO: These attributes should come from the subsequent paragraph
|
|
||||||
// when originally deleted, since the subsequent para takes on
|
|
||||||
// the previous para's attributes.
|
|
||||||
finalPara->SetAttributes(firstPara->GetAttributes());
|
|
||||||
|
|
||||||
if (nextParagraph)
|
|
||||||
InsertChild(finalPara, nextParagraph);
|
|
||||||
else
|
|
||||||
AppendChild(finalPara);
|
|
||||||
}
|
|
||||||
else while (i)
|
|
||||||
{
|
{
|
||||||
wxRichTextParagraph* para = wxDynamicCast(i->GetData(), wxRichTextParagraph);
|
wxRichTextParagraph* para = wxDynamicCast(i->GetData(), wxRichTextParagraph);
|
||||||
wxASSERT( para != NULL );
|
wxASSERT( para != NULL );
|
||||||
@@ -1195,6 +1197,18 @@ bool wxRichTextParagraphLayoutBox::InsertFragment(long position, wxRichTextParag
|
|||||||
i = i->GetNext();
|
i = i->GetNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there was only one paragraph, or we have full paragraphs in our fragment,
|
||||||
|
// we need to insert a new one.
|
||||||
|
if (needExtraPara)
|
||||||
|
{
|
||||||
|
finalPara = new wxRichTextParagraph;
|
||||||
|
|
||||||
|
if (nextParagraph)
|
||||||
|
InsertChild(finalPara, nextParagraph);
|
||||||
|
else
|
||||||
|
AppendChild(finalPara);
|
||||||
|
}
|
||||||
|
|
||||||
// 4. Add back the remaining content.
|
// 4. Add back the remaining content.
|
||||||
if (finalPara)
|
if (finalPara)
|
||||||
{
|
{
|
||||||
@@ -1204,11 +1218,15 @@ bool wxRichTextParagraphLayoutBox::InsertFragment(long position, wxRichTextParag
|
|||||||
if (finalPara->GetChildCount() == 0)
|
if (finalPara->GetChildCount() == 0)
|
||||||
{
|
{
|
||||||
wxRichTextPlainText* text = new wxRichTextPlainText(wxEmptyString);
|
wxRichTextPlainText* text = new wxRichTextPlainText(wxEmptyString);
|
||||||
|
text->SetAttributes(emptyParagraphAttributes);
|
||||||
|
|
||||||
finalPara->AppendChild(text);
|
finalPara->AppendChild(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (finalPara && finalPara != para)
|
||||||
|
finalPara->SetAttributes(originalAttr);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1392,6 +1410,7 @@ bool wxRichTextParagraphLayoutBox::DeleteRange(const wxRichTextRange& range)
|
|||||||
{
|
{
|
||||||
wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
|
wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
|
||||||
|
|
||||||
|
wxRichTextParagraph* firstPara = NULL;
|
||||||
while (node)
|
while (node)
|
||||||
{
|
{
|
||||||
wxRichTextParagraph* obj = wxDynamicCast(node->GetData(), wxRichTextParagraph);
|
wxRichTextParagraph* obj = wxDynamicCast(node->GetData(), wxRichTextParagraph);
|
||||||
@@ -1406,58 +1425,75 @@ bool wxRichTextParagraphLayoutBox::DeleteRange(const wxRichTextRange& range)
|
|||||||
// Deletes the content of this object within the given range
|
// Deletes the content of this object within the given range
|
||||||
obj->DeleteRange(range);
|
obj->DeleteRange(range);
|
||||||
|
|
||||||
|
wxRichTextRange thisRange = obj->GetRange();
|
||||||
|
|
||||||
// If the whole paragraph is within the range to delete,
|
// If the whole paragraph is within the range to delete,
|
||||||
// delete the whole thing.
|
// delete the whole thing.
|
||||||
if (range.GetStart() <= obj->GetRange().GetStart() && range.GetEnd() >= obj->GetRange().GetEnd())
|
if (range.GetStart() <= thisRange.GetStart() && range.GetEnd() >= thisRange.GetEnd())
|
||||||
{
|
{
|
||||||
// Delete the whole object
|
// Delete the whole object
|
||||||
RemoveChild(obj, true);
|
RemoveChild(obj, true);
|
||||||
|
obj = NULL;
|
||||||
}
|
}
|
||||||
|
else if (!firstPara)
|
||||||
|
firstPara = obj;
|
||||||
|
|
||||||
// If the range includes the paragraph end, we need to join this
|
// If the range includes the paragraph end, we need to join this
|
||||||
// and the next paragraph.
|
// and the next paragraph.
|
||||||
else if (range.Contains(obj->GetRange().GetEnd()))
|
if (range.GetEnd() <= thisRange.GetEnd())
|
||||||
{
|
{
|
||||||
// We need to move the objects from the next paragraph
|
// We need to move the objects from the next paragraph
|
||||||
// to this paragraph
|
// to this paragraph
|
||||||
|
|
||||||
if (next)
|
wxRichTextParagraph* nextParagraph = NULL;
|
||||||
|
if ((range.GetEnd() < thisRange.GetEnd()) && obj)
|
||||||
|
nextParagraph = obj;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
wxRichTextParagraph* nextParagraph = wxDynamicCast(next->GetData(), wxRichTextParagraph);
|
// We're ending at the end of the paragraph, so merge the _next_ paragraph.
|
||||||
next = next->GetNext();
|
if (next)
|
||||||
if (nextParagraph)
|
nextParagraph = wxDynamicCast(next->GetData(), wxRichTextParagraph);
|
||||||
{
|
|
||||||
// Delete the stuff we need to delete
|
|
||||||
nextParagraph->DeleteRange(range);
|
|
||||||
|
|
||||||
// Move the objects to the previous para
|
|
||||||
wxRichTextObjectList::compatibility_iterator node1 = nextParagraph->GetChildren().GetFirst();
|
|
||||||
|
|
||||||
while (node1)
|
|
||||||
{
|
|
||||||
wxRichTextObject* obj1 = node1->GetData();
|
|
||||||
|
|
||||||
// If the object is empty, optimise it out
|
|
||||||
if (obj1->IsEmpty())
|
|
||||||
{
|
|
||||||
delete obj1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
obj->AppendChild(obj1);
|
|
||||||
}
|
|
||||||
|
|
||||||
wxRichTextObjectList::compatibility_iterator next1 = node1->GetNext();
|
|
||||||
nextParagraph->GetChildren().Erase(node1);
|
|
||||||
|
|
||||||
node1 = next1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete the paragraph
|
|
||||||
RemoveChild(nextParagraph, true);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool applyFinalParagraphStyle = firstPara && nextParagraph && nextParagraph != firstPara;
|
||||||
|
|
||||||
|
wxTextAttrEx nextParaAttr;
|
||||||
|
if (applyFinalParagraphStyle)
|
||||||
|
nextParaAttr = nextParagraph->GetAttributes();
|
||||||
|
|
||||||
|
if (firstPara && nextParagraph && firstPara != nextParagraph)
|
||||||
|
{
|
||||||
|
// Move the objects to the previous para
|
||||||
|
wxRichTextObjectList::compatibility_iterator node1 = nextParagraph->GetChildren().GetFirst();
|
||||||
|
|
||||||
|
while (node1)
|
||||||
|
{
|
||||||
|
wxRichTextObject* obj1 = node1->GetData();
|
||||||
|
|
||||||
|
// If the object is empty, optimise it out
|
||||||
|
if (obj1->IsEmpty())
|
||||||
|
{
|
||||||
|
delete obj1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
firstPara->AppendChild(obj1);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxRichTextObjectList::compatibility_iterator next1 = node1->GetNext();
|
||||||
|
nextParagraph->GetChildren().Erase(node1);
|
||||||
|
|
||||||
|
node1 = next1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the paragraph
|
||||||
|
RemoveChild(nextParagraph, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (applyFinalParagraphStyle)
|
||||||
|
firstPara->SetAttributes(nextParaAttr);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4662,6 +4698,7 @@ bool wxRichTextPlainText::Merge(wxRichTextObject* object)
|
|||||||
if (textObject)
|
if (textObject)
|
||||||
{
|
{
|
||||||
m_text += textObject->GetText();
|
m_text += textObject->GetText();
|
||||||
|
wxRichTextApplyStyle(m_attributes, textObject->GetAttributes());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -4794,21 +4831,14 @@ bool wxRichTextBuffer::InsertParagraphsWithUndo(long pos, const wxRichTextParagr
|
|||||||
|
|
||||||
action->GetNewParagraphs() = paragraphs;
|
action->GetNewParagraphs() = paragraphs;
|
||||||
|
|
||||||
if (p)
|
|
||||||
{
|
|
||||||
wxRichTextObjectList::compatibility_iterator node = m_children.GetLast();
|
|
||||||
while (node)
|
|
||||||
{
|
|
||||||
wxRichTextParagraph* obj = (wxRichTextParagraph*) node->GetData();
|
|
||||||
obj->SetAttributes(*p);
|
|
||||||
node = node->GetPrevious();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
action->SetPosition(pos);
|
action->SetPosition(pos);
|
||||||
|
|
||||||
|
wxRichTextRange range = wxRichTextRange(pos, pos + paragraphs.GetRange().GetEnd() - 1);
|
||||||
|
if (!paragraphs.GetPartialParagraph())
|
||||||
|
range.SetEnd(range.GetEnd()+1);
|
||||||
|
|
||||||
// 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 + paragraphs.GetRange().GetEnd() - 1));
|
action->SetRange(range);
|
||||||
|
|
||||||
SubmitAction(action);
|
SubmitAction(action);
|
||||||
|
|
||||||
@@ -4878,6 +4908,10 @@ bool wxRichTextBuffer::InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl, int
|
|||||||
if (p)
|
if (p)
|
||||||
newPara->SetAttributes(*p);
|
newPara->SetAttributes(*p);
|
||||||
|
|
||||||
|
// Use the default character style
|
||||||
|
if (!GetDefaultStyle().IsDefault() && newPara->GetChildren().GetFirst())
|
||||||
|
newPara->GetChildren().GetFirst()->GetData()->SetAttributes(GetDefaultStyle());
|
||||||
|
|
||||||
// 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));
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user