]> git.saurik.com Git - wxWidgets.git/blobdiff - samples/richtext/richtext.cpp
Rebake trunk after wxWebView merge and add missing project files for the wxWebView...
[wxWidgets.git] / samples / richtext / richtext.cpp
index 23e50e2563e5538e70c827cb634934e27412061e..ef733e27b6b1a2a8ace098097cef8c6cbc092064 100644 (file)
@@ -34,6 +34,7 @@
 #include "wx/splitter.h"
 #include "wx/sstream.h"
 #include "wx/html/htmlwin.h"
+#include "wx/stopwatch.h"
 
 #if wxUSE_FILESYSTEM
 #include "wx/filesys.h"
@@ -78,6 +79,7 @@
 #include "wx/richtext/richtextsymboldlg.h"
 #include "wx/richtext/richtextstyledlg.h"
 #include "wx/richtext/richtextprint.h"
+#include "wx/richtext/richtextimagedlg.h"
 
 // ----------------------------------------------------------------------------
 // resources
@@ -145,6 +147,8 @@ public:
     void OnIndentLess(wxCommandEvent& event);
 
     void OnFont(wxCommandEvent& event);
+    void OnImage(wxCommandEvent& event);
+    void OnUpdateImage(wxUpdateUIEvent& event);
     void OnParagraph(wxCommandEvent& event);
     void OnFormat(wxCommandEvent& event);
     void OnUpdateFormat(wxUpdateUIEvent& event);
@@ -166,6 +170,8 @@ public:
     void OnDemoteList(wxCommandEvent& event);
     void OnClearList(wxCommandEvent& event);
 
+    void OnReload(wxCommandEvent& event);
+
     void OnViewHTML(wxCommandEvent& event);
 
     void OnSwitchStyleSheets(wxCommandEvent& event);
@@ -179,9 +185,15 @@ public:
     void OnPreview(wxCommandEvent& event);
     void OnPageSetup(wxCommandEvent& event);
 
+    void OnInsertImage(wxCommandEvent& event);
+protected:
+
     // Forward command events to the current rich text control, if any
     bool ProcessEvent(wxEvent& event);
 
+    // Write text
+    void WriteInitialText();
+
 private:
     // any class wishing to process wxWidgets events must use this macro
     DECLARE_EVENT_TABLE()
@@ -204,11 +216,15 @@ enum
     ID_FORMAT_ITALIC,
     ID_FORMAT_UNDERLINE,
     ID_FORMAT_FONT,
+    ID_FORMAT_IMAGE,
     ID_FORMAT_PARAGRAPH,
     ID_FORMAT_CONTENT,
 
+    ID_RELOAD,
+
     ID_INSERT_SYMBOL,
     ID_INSERT_URL,
+    ID_INSERT_IMAGE,
 
     ID_FORMAT_ALIGN_LEFT,
     ID_FORMAT_ALIGN_CENTRE,
@@ -277,10 +293,12 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
     EVT_UPDATE_UI(ID_FORMAT_ALIGN_RIGHT,  MyFrame::OnUpdateAlignRight)
 
     EVT_MENU(ID_FORMAT_FONT,  MyFrame::OnFont)
+    EVT_MENU(ID_FORMAT_IMAGE, MyFrame::OnImage)
     EVT_MENU(ID_FORMAT_PARAGRAPH,  MyFrame::OnParagraph)
     EVT_MENU(ID_FORMAT_CONTENT,  MyFrame::OnFormat)
     EVT_UPDATE_UI(ID_FORMAT_CONTENT,  MyFrame::OnUpdateFormat)
     EVT_UPDATE_UI(ID_FORMAT_FONT,  MyFrame::OnUpdateFormat)
+    EVT_UPDATE_UI(ID_FORMAT_IMAGE, MyFrame::OnUpdateImage)
     EVT_UPDATE_UI(ID_FORMAT_PARAGRAPH,  MyFrame::OnUpdateFormat)
     EVT_MENU(ID_FORMAT_INDENT_MORE,  MyFrame::OnIndentMore)
     EVT_MENU(ID_FORMAT_INDENT_LESS,  MyFrame::OnIndentLess)
@@ -292,8 +310,11 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
     EVT_MENU(ID_FORMAT_PARAGRAPH_SPACING_MORE,  MyFrame::OnParagraphSpacingMore)
     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_URL,  MyFrame::OnInsertURL)
+    EVT_MENU(ID_INSERT_IMAGE, MyFrame::OnInsertImage)
 
     EVT_MENU(ID_FORMAT_NUMBER_LIST, MyFrame::OnNumberList)
     EVT_MENU(ID_FORMAT_BULLETS_AND_NUMBERING, MyFrame::OnBulletsAndNumbering)
@@ -370,7 +391,7 @@ bool MyApp::OnInit()
 #endif
 
     // create the main application window
-    MyFrame *frame = new MyFrame(_T("wxRichTextCtrl Sample"), wxID_ANY, wxDefaultPosition, wxSize(700, 600));
+    MyFrame *frame = new MyFrame(wxT("wxRichTextCtrl Sample"), wxID_ANY, wxDefaultPosition, wxSize(700, 600));
 
     m_printing->SetParentWindow(frame);
 
@@ -426,7 +447,7 @@ void MyApp::CreateStyles()
     wxRichTextAttr indentedAttr2;
     indentedAttr2.SetFontFaceName(romanFont.GetFaceName());
     indentedAttr2.SetFontSize(12);
-    indentedAttr2.SetFontWeight(wxBOLD);
+    indentedAttr2.SetFontWeight(wxFONTWEIGHT_BOLD);
     indentedAttr2.SetTextColour(*wxRED);
     indentedAttr2.SetFontSize(12);
     indentedAttr2.SetLeftIndent(100, 0);
@@ -453,7 +474,7 @@ void MyApp::CreateStyles()
     wxRichTextAttr boldAttr;
     boldAttr.SetFontFaceName(romanFont.GetFaceName());
     boldAttr.SetFontSize(12);
-    boldAttr.SetFontWeight(wxBOLD);
+    boldAttr.SetFontWeight(wxFONTWEIGHT_BOLD);
     // We only want to affect boldness
     boldAttr.SetFlags(wxTEXT_ATTR_FONT_WEIGHT);
     boldDef->SetStyle(boldAttr);
@@ -464,7 +485,7 @@ void MyApp::CreateStyles()
     wxRichTextAttr italicAttr;
     italicAttr.SetFontFaceName(romanFont.GetFaceName());
     italicAttr.SetFontSize(12);
-    italicAttr.SetFontStyle(wxITALIC);
+    italicAttr.SetFontStyle(wxFONTSTYLE_ITALIC);
     // We only want to affect italics
     italicAttr.SetFlags(wxTEXT_ATTR_FONT_ITALIC);
     italicDef->SetStyle(italicAttr);
@@ -475,7 +496,7 @@ void MyApp::CreateStyles()
     wxRichTextAttr redAttr;
     redAttr.SetFontFaceName(romanFont.GetFaceName());
     redAttr.SetFontSize(12);
-    redAttr.SetFontWeight(wxBOLD);
+    redAttr.SetFontWeight(wxFONTWEIGHT_BOLD);
     redAttr.SetTextColour(*wxRED);
     // We only want to affect colour, weight and face
     redAttr.SetFlags(wxTEXT_ATTR_FONT_FACE|wxTEXT_ATTR_FONT_WEIGHT|wxTEXT_ATTR_TEXT_COLOUR);
@@ -558,19 +579,21 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
 
     // the "About" item should be in the help menu
     wxMenu *helpMenu = new wxMenu;
-    helpMenu->Append(ID_About, _T("&About...\tF1"), _T("Show about dialog"));
+    helpMenu->Append(ID_About, wxT("&About...\tF1"), wxT("Show about dialog"));
 
-    fileMenu->Append(wxID_OPEN, _T("&Open\tCtrl+O"), _T("Open 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_OPEN, wxT("&Open\tCtrl+O"), wxT("Open a file"));
+    fileMenu->Append(wxID_SAVE, wxT("&Save\tCtrl+S"), wxT("Save a file"));
+    fileMenu->Append(wxID_SAVEAS, wxT("&Save As...\tF12"), wxT("Save to a new file"));
     fileMenu->AppendSeparator();
-    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_PREVIEW, _T("Print Pre&view"), _T("Print preview"));
+    fileMenu->Append(ID_RELOAD, wxT("&Reload Text\tF2"), wxT("Reload the initial text"));
     fileMenu->AppendSeparator();
-    fileMenu->Append(ID_VIEW_HTML, _T("&View as HTML"), _T("View HTML"));
+    fileMenu->Append(ID_PAGE_SETUP, wxT("Page Set&up..."), wxT("Page setup"));
+    fileMenu->Append(ID_PRINT, wxT("&Print...\tCtrl+P"), wxT("Print"));
+    fileMenu->Append(ID_PREVIEW, wxT("Print Pre&view"), wxT("Print preview"));
     fileMenu->AppendSeparator();
-    fileMenu->Append(ID_Quit, _T("E&xit\tAlt+X"), _T("Quit this program"));
+    fileMenu->Append(ID_VIEW_HTML, wxT("&View as HTML"), wxT("View HTML"));
+    fileMenu->AppendSeparator();
+    fileMenu->Append(ID_Quit, wxT("E&xit\tAlt+X"), wxT("Quit this program"));
 
     wxMenu* editMenu = new wxMenu;
     editMenu->Append(wxID_UNDO, _("&Undo\tCtrl+Z"));
@@ -608,6 +631,7 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
     formatMenu->Append(ID_FORMAT_LINE_SPACING_DOUBLE, _("Double Line Spacing"));
     formatMenu->AppendSeparator();
     formatMenu->Append(ID_FORMAT_FONT, _("&Font..."));
+    formatMenu->Append(ID_FORMAT_IMAGE, _("Image Property"));
     formatMenu->Append(ID_FORMAT_PARAGRAPH, _("&Paragraph..."));
     formatMenu->Append(ID_FORMAT_CONTENT, _("Font and Pa&ragraph...\tShift+Ctrl+F"));
     formatMenu->AppendSeparator();
@@ -627,15 +651,16 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
     wxMenu* insertMenu = new wxMenu;
     insertMenu->Append(ID_INSERT_SYMBOL, _("&Symbol...\tCtrl+I"));
     insertMenu->Append(ID_INSERT_URL, _("&URL..."));
+    insertMenu->Append(ID_INSERT_IMAGE, _("&Image..."));
 
     // now append the freshly created menu to the menu bar...
     wxMenuBar *menuBar = new wxMenuBar();
-    menuBar->Append(fileMenu, _T("&File"));
-    menuBar->Append(editMenu, _T("&Edit"));
-    menuBar->Append(formatMenu, _T("F&ormat"));
-    menuBar->Append(listsMenu, _T("&Lists"));
-    menuBar->Append(insertMenu, _T("&Insert"));
-    menuBar->Append(helpMenu, _T("&Help"));
+    menuBar->Append(fileMenu, wxT("&File"));
+    menuBar->Append(editMenu, wxT("&Edit"));
+    menuBar->Append(formatMenu, wxT("F&ormat"));
+    menuBar->Append(listsMenu, wxT("&Lists"));
+    menuBar->Append(insertMenu, wxT("&Insert"));
+    menuBar->Append(helpMenu, wxT("&Help"));
 
     // ... and attach this menu bar to the frame
     SetMenuBar(menuBar);
@@ -648,34 +673,35 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
     if ( !is_pda )
     {
         CreateStatusBar(2);
-        SetStatusText(_T("Welcome to wxRichTextCtrl!"));
+        SetStatusText(wxT("Welcome to wxRichTextCtrl!"));
     }
 #endif
 
     wxToolBar* toolBar = CreateToolBar();
 
-    toolBar->AddTool(wxID_OPEN, wxBitmap(open_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Open"));
-    toolBar->AddTool(wxID_SAVEAS, wxBitmap(save_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Save"));
+    toolBar->AddTool(wxID_OPEN, wxEmptyString, wxBitmap(open_xpm), _("Open"));
+    toolBar->AddTool(wxID_SAVEAS, wxEmptyString, wxBitmap(save_xpm), _("Save"));
     toolBar->AddSeparator();
-    toolBar->AddTool(wxID_CUT, wxBitmap(cut_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Cut"));
-    toolBar->AddTool(wxID_COPY, wxBitmap(copy_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Copy"));
-    toolBar->AddTool(wxID_PASTE, wxBitmap(paste_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Paste"));
+    toolBar->AddTool(wxID_CUT, wxEmptyString, wxBitmap(cut_xpm), _("Cut"));
+    toolBar->AddTool(wxID_COPY, wxEmptyString, wxBitmap(copy_xpm), _("Copy"));
+    toolBar->AddTool(wxID_PASTE, wxEmptyString, wxBitmap(paste_xpm), _("Paste"));
     toolBar->AddSeparator();
-    toolBar->AddTool(wxID_UNDO, wxBitmap(undo_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Undo"));
-    toolBar->AddTool(wxID_REDO, wxBitmap(redo_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Redo"));
+    toolBar->AddTool(wxID_UNDO, wxEmptyString, wxBitmap(undo_xpm), _("Undo"));
+    toolBar->AddTool(wxID_REDO, wxEmptyString, wxBitmap(redo_xpm), _("Redo"));
     toolBar->AddSeparator();
-    toolBar->AddTool(ID_FORMAT_BOLD, wxBitmap(bold_xpm), wxNullBitmap, true, -1, -1, (wxObject *) NULL, _("Bold"));
-    toolBar->AddTool(ID_FORMAT_ITALIC, wxBitmap(italic_xpm), wxNullBitmap, true, -1, -1, (wxObject *) NULL, _("Italic"));
-    toolBar->AddTool(ID_FORMAT_UNDERLINE, wxBitmap(underline_xpm), wxNullBitmap, true, -1, -1, (wxObject *) NULL, _("Underline"));
+    toolBar->AddCheckTool(ID_FORMAT_BOLD, wxEmptyString, wxBitmap(bold_xpm), wxNullBitmap, _("Bold"));
+    toolBar->AddCheckTool(ID_FORMAT_ITALIC, wxEmptyString, wxBitmap(italic_xpm), wxNullBitmap, _("Italic"));
+    toolBar->AddCheckTool(ID_FORMAT_UNDERLINE, wxEmptyString, wxBitmap(underline_xpm), wxNullBitmap, _("Underline"));
     toolBar->AddSeparator();
-    toolBar->AddTool(ID_FORMAT_ALIGN_LEFT, wxBitmap(alignleft_xpm), wxNullBitmap, true, -1, -1, (wxObject *) NULL, _("Align Left"));
-    toolBar->AddTool(ID_FORMAT_ALIGN_CENTRE, wxBitmap(centre_xpm), wxNullBitmap, true, -1, -1, (wxObject *) NULL, _("Centre"));
-    toolBar->AddTool(ID_FORMAT_ALIGN_RIGHT, wxBitmap(alignright_xpm), wxNullBitmap, true, -1, -1, (wxObject *) NULL, _("Align Right"));
+    toolBar->AddCheckTool(ID_FORMAT_ALIGN_LEFT, wxEmptyString, wxBitmap(alignleft_xpm), wxNullBitmap, _("Align Left"));
+    toolBar->AddCheckTool(ID_FORMAT_ALIGN_CENTRE, wxEmptyString, wxBitmap(centre_xpm), wxNullBitmap, _("Centre"));
+    toolBar->AddCheckTool(ID_FORMAT_ALIGN_RIGHT, wxEmptyString, wxBitmap(alignright_xpm), wxNullBitmap, _("Align Right"));
     toolBar->AddSeparator();
-    toolBar->AddTool(ID_FORMAT_INDENT_LESS, wxBitmap(indentless_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Indent Less"));
-    toolBar->AddTool(ID_FORMAT_INDENT_MORE, wxBitmap(indentmore_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Indent More"));
+    toolBar->AddTool(ID_FORMAT_INDENT_LESS, wxEmptyString, wxBitmap(indentless_xpm), _("Indent Less"));
+    toolBar->AddTool(ID_FORMAT_INDENT_MORE, wxEmptyString, wxBitmap(indentmore_xpm), _("Indent More"));
     toolBar->AddSeparator();
-    toolBar->AddTool(ID_FORMAT_FONT, wxBitmap(font_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Font"));
+    toolBar->AddTool(ID_FORMAT_FONT, wxEmptyString, wxBitmap(font_xpm), _("Font"));
+    toolBar->AddTool(ID_FORMAT_IMAGE, wxString("Im"), wxBitmap(font_xpm), _("Image Property"));
 
     wxRichTextStyleComboCtrl* combo = new wxRichTextStyleComboCtrl(toolBar, ID_RICHTEXT_STYLE_COMBO, wxDefaultPosition, wxSize(200, -1));
     toolBar->AddControl(combo);
@@ -693,6 +719,8 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
 
     m_richTextCtrl->SetFont(font);
 
+    m_richTextCtrl->SetMargins(10, 10);
+
     m_richTextCtrl->SetStyleSheet(wxGetApp().GetStyleSheet());
 
     combo->SetStyleSheet(wxGetApp().GetStyleSheet());
@@ -717,10 +745,21 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
     styleListCtrl->SetRichTextCtrl(m_richTextCtrl);
     styleListCtrl->UpdateStyles();
 
+    WriteInitialText();
+}
+
+// Write text
+void MyFrame::WriteInitialText()
+{
     wxRichTextCtrl& r = *m_richTextCtrl;
 
+    r.SetDefaultStyle(wxRichTextAttr());
+
     r.BeginSuppressUndo();
 
+    r.Freeze();
+
+#if 1
     r.BeginParagraphSpacing(0, 20);
 
     r.BeginAlignment(wxTEXT_ALIGNMENT_CENTRE);
@@ -730,9 +769,8 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
 
     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.Newline();
 
     r.BeginItalic();
     r.WriteText(wxT("by Julian Smart"));
@@ -743,9 +781,22 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
 
     r.WriteImage(wxBitmap(zebra_xpm));
 
+    r.Newline();
+    r.Newline();
+
     r.EndAlignment();
 
-    r.Newline();
+    r.BeginAlignment(wxTEXT_ALIGNMENT_LEFT);
+    wxRichTextAttr imageAttr;
+    imageAttr.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_LEFT);
+    r.WriteText(wxString(wxT("This is a simple test for a floating left image test. The zebra image should be placed at the left side of the current buffer and all the text should flow around it at the right side. This is a simple test for a floating left image test. The zebra image should be placed at the left side of the current buffer and all the text should flow around it at the right side. This is a simple test for a floating left image test. The zebra image should be placed at the left side of the current buffer and all the text should flow around it at the right side.")));
+    r.WriteImage(wxBitmap(zebra_xpm), wxBITMAP_TYPE_PNG, imageAttr);
+    imageAttr.GetTextBoxAttr().GetTop().SetValue(200);
+    imageAttr.GetTextBoxAttr().GetTop().SetUnits(wxTEXT_ATTR_UNITS_PIXELS);
+    imageAttr.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_RIGHT);
+    r.WriteImage(wxBitmap(zebra_xpm), wxBITMAP_TYPE_PNG, imageAttr);
+    r.WriteText(wxString(wxT("This is a simple test for a floating right image test. The zebra image should be placed at the right side of the current buffer and all the text should flow around it at the left side. This is a simple test for a floating left image test. The zebra image should be placed at the right side of the current buffer and all the text should flow around it at the left side. This is a simple test for a floating left image test. The zebra image should be placed at the right side of the current buffer and all the text should flow around it at the left side.")));
+    r.EndAlignment();
     r.Newline();
 
     r.WriteText(wxT("What can you do with this thing? "));
@@ -781,57 +832,55 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
 
     r.WriteText(wxT(" Next we'll show an indented paragraph."));
 
-    r.BeginLeftIndent(60);
     r.Newline();
 
+    r.BeginLeftIndent(60);
     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.EndLeftIndent();
+
     r.WriteText(wxT("Next, we'll show a first-line indent, achieved using BeginLeftIndent(100, -40)."));
 
-    r.BeginLeftIndent(100, -40);
     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.EndLeftIndent();
+    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.Newline();
 
-    r.WriteText(wxT("Numbered bullets are possible, again using subindents:"));
+    r.EndLeftIndent();
 
-    r.BeginNumberedBullet(1, 100, 60);
+    r.WriteText(wxT("Numbered bullets are possible, again using subindents:"));
     r.Newline();
 
+    r.BeginNumberedBullet(1, 100, 60);
     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.BeginNumberedBullet(2, 100, 60);
-    r.Newline();
-
     r.WriteText(wxT("This is my second item."));
-    r.EndNumberedBullet();
-
     r.Newline();
+    r.EndNumberedBullet();
 
     r.WriteText(wxT("The following paragraph is right-indented:"));
+    r.Newline();
 
     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.EndRightIndent();
-
     r.Newline();
 
+    r.EndRightIndent();
+
     r.WriteText(wxT("The following paragraph is right-aligned with 1.5 line spacing:"));
+    r.Newline();
 
     r.BeginAlignment(wxTEXT_ALIGNMENT_RIGHT);
     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.Newline();
     r.EndLineSpacing();
     r.EndAlignment();
 
@@ -845,48 +894,46 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
     attr.SetTabs(tabs);
     r.SetDefaultStyle(attr);
 
-    r.Newline();
     r.WriteText(wxT("This line contains tabs:\tFirst tab\tSecond tab\tThird tab"));
-
     r.Newline();
+
     r.WriteText(wxT("Other notable features of wxRichTextCtrl include:"));
+    r.Newline();
 
     r.BeginSymbolBullet(wxT('*'), 100, 60);
-    r.Newline();
     r.WriteText(wxT("Compatibility with wxTextCtrl API"));
+    r.Newline();
     r.EndSymbolBullet();
 
     r.BeginSymbolBullet(wxT('*'), 100, 60);
-    r.Newline();
     r.WriteText(wxT("Easy stack-based BeginXXX()...EndXXX() style setting in addition to SetStyle()"));
+    r.Newline();
     r.EndSymbolBullet();
 
     r.BeginSymbolBullet(wxT('*'), 100, 60);
-    r.Newline();
     r.WriteText(wxT("XML loading and saving"));
+    r.Newline();
     r.EndSymbolBullet();
 
     r.BeginSymbolBullet(wxT('*'), 100, 60);
-    r.Newline();
     r.WriteText(wxT("Undo/Redo, with batching option and Undo suppressing"));
+    r.Newline();
     r.EndSymbolBullet();
 
     r.BeginSymbolBullet(wxT('*'), 100, 60);
-    r.Newline();
     r.WriteText(wxT("Clipboard copy and paste"));
+    r.Newline();
     r.EndSymbolBullet();
 
     r.BeginSymbolBullet(wxT('*'), 100, 60);
-    r.Newline();
     r.WriteText(wxT("wxRichTextStyleSheet with named character and paragraph styles, and control for applying named styles"));
+    r.Newline();
     r.EndSymbolBullet();
 
     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.EndSymbolBullet();
-
     r.Newline();
+    r.EndSymbolBullet();
 
     // Make a style suitable for showing a URL
     wxRichTextAttr urlStyle;
@@ -903,14 +950,77 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
 
     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();
+#endif
+#if 1
+
+    {
+        // Add a text box
+
+        r.Newline();
+        
+        wxRichTextAttr attr;
+        attr.GetTextBoxAttr().GetMargins().GetLeft().SetValue(20, wxTEXT_ATTR_UNITS_PIXELS);
+        attr.GetTextBoxAttr().GetMargins().GetTop().SetValue(20, wxTEXT_ATTR_UNITS_PIXELS);
+        attr.GetTextBoxAttr().GetMargins().GetRight().SetValue(20, wxTEXT_ATTR_UNITS_PIXELS);
+        attr.GetTextBoxAttr().GetMargins().GetBottom().SetValue(20, wxTEXT_ATTR_UNITS_PIXELS);
+
+        attr.GetTextBoxAttr().GetBorder().SetColour(*wxBLACK);
+        attr.GetTextBoxAttr().GetBorder().SetWidth(1, wxTEXT_ATTR_UNITS_PIXELS);
+        attr.GetTextBoxAttr().GetBorder().SetStyle(wxTEXT_BOX_ATTR_BORDER_SOLID);
+
+        wxRichTextBox* textBox = r.WriteTextBox(attr);
+        r.SetFocusObject(textBox);
+
+        r.WriteText(wxT("This is a text box. Just testing! Once more unto the breach, dear friends, once more..."));
+
+        r.SetFocusObject(NULL); // Set the focus back to the main buffer
+        r.SetInsertionPointEnd();
+    }
+#endif
+#if 1
+    {
+        // Add a table
+
+        r.Newline();
+        
+        wxRichTextAttr attr;
+        attr.GetTextBoxAttr().GetMargins().GetLeft().SetValue(5, wxTEXT_ATTR_UNITS_PIXELS);
+        attr.GetTextBoxAttr().GetMargins().GetTop().SetValue(5, wxTEXT_ATTR_UNITS_PIXELS);
+        attr.GetTextBoxAttr().GetMargins().GetRight().SetValue(5, wxTEXT_ATTR_UNITS_PIXELS);
+        attr.GetTextBoxAttr().GetMargins().GetBottom().SetValue(5, wxTEXT_ATTR_UNITS_PIXELS);
+        attr.GetTextBoxAttr().GetPadding() = attr.GetTextBoxAttr().GetMargins();
+
+        attr.GetTextBoxAttr().GetBorder().SetColour(*wxBLACK);
+        attr.GetTextBoxAttr().GetBorder().SetWidth(1, wxTEXT_ATTR_UNITS_PIXELS);
+        attr.GetTextBoxAttr().GetBorder().SetStyle(wxTEXT_BOX_ATTR_BORDER_SOLID);
+
+        wxRichTextAttr cellAttr = attr;
+        cellAttr.GetTextBoxAttr().GetWidth().SetValue(200, wxTEXT_ATTR_UNITS_PIXELS);
+        cellAttr.GetTextBoxAttr().GetHeight().SetValue(150, wxTEXT_ATTR_UNITS_PIXELS);
+
+        wxRichTextTable* table = r.WriteTable(3, 2, attr, cellAttr);
+        int i, j;
+        for (j = 0; j < table->GetRowCount(); j++)
+        {
+            for (i = 0; i < table->GetColumnCount(); i++)
+            {
+                wxString msg = wxString::Format(wxT("This is cell %d, %d"), (j+1), (i+1));
+                r.SetFocusObject(table->GetCell(j, i));
+                r.WriteText(msg);
+            }
+        }
+        r.SetFocusObject(NULL); // Set the focus back to the main buffer
+        r.SetInsertionPointEnd();
+    }
+#endif
+    r.Thaw();
 
     r.EndSuppressUndo();
 }
 
-
 // event handlers
 
 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
@@ -922,8 +1032,8 @@ void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
 {
     wxString msg;
-    msg.Printf( _T("This is a demo for wxRichTextCtrl, a control for editing styled text.\n(c) Julian Smart, 2005"));
-    wxMessageBox(msg, _T("About wxRichTextCtrl Sample"), wxOK | wxICON_INFORMATION, this);
+    msg.Printf( wxT("This is a demo for wxRichTextCtrl, a control for editing styled text.\n(c) Julian Smart, 2005"));
+    wxMessageBox(msg, wxT("About wxRichTextCtrl Sample"), wxOK | wxICON_INFORMATION, this);
 }
 
 // Forward command events to the current rich text control, if any
@@ -945,7 +1055,7 @@ bool MyFrame::ProcessEvent(wxEvent& event)
             s_id = event.GetId();
 
             wxWindow* focusWin = wxFindFocusDescendant(this);
-            if (focusWin && focusWin->ProcessEvent(event))
+            if (focusWin && focusWin->GetEventHandler()->ProcessEvent(event))
             {
                 //s_command = NULL;
                 s_eventType = 0;
@@ -1027,7 +1137,14 @@ void MyFrame::OnSaveAs(wxCommandEvent& WXUNUSED(event))
 
         if (!path.empty())
         {
+            wxBusyCursor busy;
+            wxStopWatch stopwatch;
+
             m_richTextCtrl->SaveFile(path);
+
+            long t = stopwatch.Time();
+            wxLogDebug(wxT("Saving took %ldms"), t);
+            wxMessageBox(wxString::Format(wxT("Saving took %ldms"), t));
         }
     }
 }
@@ -1119,7 +1236,7 @@ void MyFrame::OnFont(wxCommandEvent& WXUNUSED(event))
     wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
     wxFontData fontData;
 
-    wxTextAttrEx attr;
+    wxRichTextAttr attr;
     attr.SetFlags(wxTEXT_ATTR_FONT);
 
     if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
@@ -1131,7 +1248,7 @@ void MyFrame::OnFont(wxCommandEvent& WXUNUSED(event))
         fontData = dialog.GetFontData();
         attr.SetFlags(wxTEXT_ATTR_FONT);
         attr.SetFont(fontData.GetChosenFont());
-        if (attr.GetFont().Ok())
+        if (attr.GetFont().IsOk())
         {
             m_richTextCtrl->SetStyle(range, attr);
         }
@@ -1139,6 +1256,26 @@ void MyFrame::OnFont(wxCommandEvent& WXUNUSED(event))
 #endif
 }
 
+void MyFrame::OnImage(wxCommandEvent& WXUNUSED(event))
+{
+    wxRichTextRange range;
+    wxASSERT(m_richTextCtrl->HasSelection());
+
+    range = m_richTextCtrl->GetSelectionRange();
+    wxASSERT(range.ToInternal().GetLength() == 1);
+
+    wxRichTextImage* image = wxDynamicCast(m_richTextCtrl->GetFocusObject()->GetLeafObjectAtPosition(range.GetStart()), wxRichTextImage);
+    if (image)
+    {
+        wxRichTextObjectPropertiesDialog imageDlg(image, this);
+
+        if (imageDlg.ShowModal() == wxID_OK)
+        {
+            imageDlg.ApplyStyle(m_richTextCtrl);
+        }
+    }
+}
+
 void MyFrame::OnParagraph(wxCommandEvent& WXUNUSED(event))
 {
     wxRichTextRange range;
@@ -1182,6 +1319,25 @@ void MyFrame::OnUpdateFormat(wxUpdateUIEvent& event)
     event.Enable(m_richTextCtrl->HasSelection());
 }
 
+void MyFrame::OnUpdateImage(wxUpdateUIEvent& event)
+{
+    wxRichTextRange range;
+    wxRichTextObject *obj;
+
+    range = m_richTextCtrl->GetSelectionRange();
+    if (range.ToInternal().GetLength() == 1)
+    {
+        obj = m_richTextCtrl->GetFocusObject()->GetLeafObjectAtPosition(range.GetStart());
+        if (obj && obj->IsKindOf(CLASSINFO(wxRichTextImage)))
+        {
+            event.Enable(true);
+            return;
+        }
+    }
+
+    event.Enable(false);
+}
+
 void MyFrame::OnIndentMore(wxCommandEvent& WXUNUSED(event))
 {
     wxRichTextAttr attr;
@@ -1313,6 +1469,12 @@ void MyFrame::OnParagraphSpacingLess(wxCommandEvent& WXUNUSED(event))
     }
 }
 
+void MyFrame::OnReload(wxCommandEvent& WXUNUSED(event))
+{
+    m_richTextCtrl->Clear();
+    WriteInitialText();
+}
+
 void MyFrame::OnViewHTML(wxCommandEvent& WXUNUSED(event))
 {
     wxDialog dialog(this, wxID_ANY, _("HTML"), wxDefaultPosition, wxSize(500, 400), wxDEFAULT_DIALOG_STYLE);
@@ -1427,7 +1589,7 @@ void MyFrame::OnInsertSymbol(wxCommandEvent& WXUNUSED(event))
     m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr);
 
     wxString currentFontName;
-    if (attr.HasFont() && attr.GetFont().Ok())
+    if (attr.HasFont() && attr.GetFont().IsOk())
         currentFontName = attr.GetFont().GetFaceName();
 
     // Don't set the initial font in the dialog (so the user is choosing
@@ -1541,6 +1703,16 @@ void MyFrame::OnInsertURL(wxCommandEvent& WXUNUSED(event))
     }
 }
 
+void MyFrame::OnInsertImage(wxCommandEvent& WXUNUSED(event))
+{
+    wxFileDialog dialog(this, _("Choose an image"), "", "", "BMP and GIF files (*.bmp;*.gif)|*.bmp;*.gif|PNG files (*.png)|*.png");
+    if (dialog.ShowModal() == wxID_OK)
+    {
+        wxString path = dialog.GetPath();
+        m_richTextCtrl->WriteImage(path, wxBITMAP_TYPE_ANY);
+    }
+}
+
 void MyFrame::OnURL(wxTextUrlEvent& event)
 {
     wxMessageBox(event.GetString());
@@ -1565,5 +1737,21 @@ void MyFrame::OnPreview(wxCommandEvent& WXUNUSED(event))
 
 void MyFrame::OnPageSetup(wxCommandEvent& WXUNUSED(event))
 {
-    wxGetApp().GetPrinting()->PageSetup();
+    wxDialog dialog(this, wxID_ANY, wxT("Testing"), wxPoint(10, 10), wxSize(400, 300), wxDEFAULT_DIALOG_STYLE);
+
+    wxNotebook* nb = new wxNotebook(& dialog, wxID_ANY, wxPoint(5, 5), wxSize(300, 250));
+    wxPanel* panel = new wxPanel(nb, wxID_ANY, wxDefaultPosition, wxDefaultSize);
+    wxPanel* panel2 = new wxPanel(nb, wxID_ANY, wxDefaultPosition, wxDefaultSize);
+
+    new wxRichTextCtrl(panel, wxID_ANY, wxEmptyString, wxPoint(5, 5), wxSize(200, 150), wxVSCROLL|wxTE_READONLY);
+    nb->AddPage(panel, wxT("Page 1"));
+
+    new wxRichTextCtrl(panel2, wxID_ANY, wxEmptyString, wxPoint(5, 5), wxSize(200, 150), wxVSCROLL|wxTE_READONLY);
+    nb->AddPage(panel2, wxT("Page 2"));
+
+    new wxButton(& dialog, wxID_OK, wxT("OK"), wxPoint(5, 180));
+
+    dialog.ShowModal();
+
+//    wxGetApp().GetPrinting()->PageSetup();
 }