1 /////////////////////////////////////////////////////////////////////////////
2 // Name: samples/richtext/richtext.cpp
3 // Purpose: wxWidgets rich text editor sample
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx/wx.h".
21 #include "wx/wxprec.h"
27 // for all others, include the necessary headers (this file is usually all you
28 // need because it includes almost all "standard" wxWidgets headers)
33 #include "wx/fontdlg.h"
34 #include "wx/splitter.h"
35 #include "wx/sstream.h"
36 #include "wx/html/htmlwin.h"
39 #include "../sample.xpm"
42 #include "bitmaps/smiley.xpm"
43 // #include "bitmaps/idea.xpm"
44 #include "bitmaps/zebra.xpm"
46 #include "bitmaps/open.xpm"
47 #include "bitmaps/save.xpm"
48 #include "bitmaps/copy.xpm"
49 #include "bitmaps/cut.xpm"
50 #include "bitmaps/paste.xpm"
51 #include "bitmaps/undo.xpm"
52 #include "bitmaps/redo.xpm"
53 #include "bitmaps/bold.xpm"
54 #include "bitmaps/italic.xpm"
55 #include "bitmaps/underline.xpm"
57 #include "bitmaps/alignleft.xpm"
58 #include "bitmaps/alignright.xpm"
59 #include "bitmaps/centre.xpm"
60 #include "bitmaps/font.xpm"
61 #include "bitmaps/indentless.xpm"
62 #include "bitmaps/indentmore.xpm"
64 #include "wx/richtext/richtextctrl.h"
65 #include "wx/richtext/richtextstyles.h"
66 #include "wx/richtext/richtextxml.h"
67 #include "wx/richtext/richtexthtml.h"
69 // ----------------------------------------------------------------------------
71 // ----------------------------------------------------------------------------
73 // ----------------------------------------------------------------------------
75 // ----------------------------------------------------------------------------
77 // Define a new application type, each program should derive a class from wxApp
78 class MyApp
: public wxApp
81 // override base class virtuals
82 // ----------------------------
84 // this one is called on application startup and is a good place for the app
85 // initialization (doing it here and not in the ctor allows to have an error
86 // return: if OnInit() returns false, the application terminates)
87 virtual bool OnInit();
92 wxRichTextStyleSheet
* GetStyleSheet() const { return m_styleSheet
; }
94 wxRichTextStyleSheet
* m_styleSheet
;
97 // Define a new frame type: this is going to be our main frame
98 class MyFrame
: public wxFrame
102 MyFrame(const wxString
& title
, wxWindowID id
, const wxPoint
& pos
= wxDefaultPosition
,
103 const wxSize
& size
= wxDefaultSize
, long style
= wxDEFAULT_FRAME_STYLE
);
105 // event handlers (these functions should _not_ be virtual)
106 void OnQuit(wxCommandEvent
& event
);
107 void OnAbout(wxCommandEvent
& event
);
109 void OnOpen(wxCommandEvent
& event
);
110 void OnSave(wxCommandEvent
& event
);
111 void OnSaveAs(wxCommandEvent
& event
);
113 void OnBold(wxCommandEvent
& event
);
114 void OnItalic(wxCommandEvent
& event
);
115 void OnUnderline(wxCommandEvent
& event
);
117 void OnUpdateBold(wxUpdateUIEvent
& event
);
118 void OnUpdateItalic(wxUpdateUIEvent
& event
);
119 void OnUpdateUnderline(wxUpdateUIEvent
& event
);
121 void OnAlignLeft(wxCommandEvent
& event
);
122 void OnAlignCentre(wxCommandEvent
& event
);
123 void OnAlignRight(wxCommandEvent
& event
);
125 void OnUpdateAlignLeft(wxUpdateUIEvent
& event
);
126 void OnUpdateAlignCentre(wxUpdateUIEvent
& event
);
127 void OnUpdateAlignRight(wxUpdateUIEvent
& event
);
129 void OnFont(wxCommandEvent
& event
);
130 void OnIndentMore(wxCommandEvent
& event
);
131 void OnIndentLess(wxCommandEvent
& event
);
133 void OnLineSpacingHalf(wxCommandEvent
& event
);
134 void OnLineSpacingDouble(wxCommandEvent
& event
);
135 void OnLineSpacingSingle(wxCommandEvent
& event
);
137 void OnParagraphSpacingMore(wxCommandEvent
& event
);
138 void OnParagraphSpacingLess(wxCommandEvent
& event
);
140 void OnViewHTML(wxCommandEvent
& event
);
142 // Forward command events to the current rich text control, if any
143 bool ProcessEvent(wxEvent
& event
);
146 // any class wishing to process wxWidgets events must use this macro
147 DECLARE_EVENT_TABLE()
149 wxRichTextCtrl
* m_richTextCtrl
;
152 // ----------------------------------------------------------------------------
154 // ----------------------------------------------------------------------------
156 // IDs for the controls and the menu commands
161 ID_About
= wxID_ABOUT
,
163 ID_FORMAT_BOLD
= 100,
168 ID_FORMAT_ALIGN_LEFT
,
169 ID_FORMAT_ALIGN_CENTRE
,
170 ID_FORMAT_ALIGN_RIGHT
,
172 ID_FORMAT_INDENT_MORE
,
173 ID_FORMAT_INDENT_LESS
,
175 ID_FORMAT_PARAGRAPH_SPACING_MORE
,
176 ID_FORMAT_PARAGRAPH_SPACING_LESS
,
178 ID_FORMAT_LINE_SPACING_HALF
,
179 ID_FORMAT_LINE_SPACING_DOUBLE
,
180 ID_FORMAT_LINE_SPACING_SINGLE
,
185 // ----------------------------------------------------------------------------
186 // event tables and other macros for wxWidgets
187 // ----------------------------------------------------------------------------
189 // the event tables connect the wxWidgets events with the functions (event
190 // handlers) which process them. It can be also done at run-time, but for the
191 // simple menu events like this the static method is much simpler.
192 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
193 EVT_MENU(ID_Quit
, MyFrame::OnQuit
)
194 EVT_MENU(ID_About
, MyFrame::OnAbout
)
196 EVT_MENU(wxID_OPEN
, MyFrame::OnOpen
)
197 EVT_MENU(wxID_SAVE
, MyFrame::OnSave
)
198 EVT_MENU(wxID_SAVEAS
, MyFrame::OnSaveAs
)
200 EVT_MENU(ID_FORMAT_BOLD
, MyFrame::OnBold
)
201 EVT_MENU(ID_FORMAT_ITALIC
, MyFrame::OnItalic
)
202 EVT_MENU(ID_FORMAT_UNDERLINE
, MyFrame::OnUnderline
)
204 EVT_UPDATE_UI(ID_FORMAT_BOLD
, MyFrame::OnUpdateBold
)
205 EVT_UPDATE_UI(ID_FORMAT_ITALIC
, MyFrame::OnUpdateItalic
)
206 EVT_UPDATE_UI(ID_FORMAT_UNDERLINE
, MyFrame::OnUpdateUnderline
)
208 EVT_MENU(ID_FORMAT_ALIGN_LEFT
, MyFrame::OnAlignLeft
)
209 EVT_MENU(ID_FORMAT_ALIGN_CENTRE
, MyFrame::OnAlignCentre
)
210 EVT_MENU(ID_FORMAT_ALIGN_RIGHT
, MyFrame::OnAlignRight
)
212 EVT_UPDATE_UI(ID_FORMAT_ALIGN_LEFT
, MyFrame::OnUpdateAlignLeft
)
213 EVT_UPDATE_UI(ID_FORMAT_ALIGN_CENTRE
, MyFrame::OnUpdateAlignCentre
)
214 EVT_UPDATE_UI(ID_FORMAT_ALIGN_RIGHT
, MyFrame::OnUpdateAlignRight
)
216 EVT_MENU(ID_FORMAT_FONT
, MyFrame::OnFont
)
217 EVT_MENU(ID_FORMAT_INDENT_MORE
, MyFrame::OnIndentMore
)
218 EVT_MENU(ID_FORMAT_INDENT_LESS
, MyFrame::OnIndentLess
)
220 EVT_MENU(ID_FORMAT_LINE_SPACING_HALF
, MyFrame::OnLineSpacingHalf
)
221 EVT_MENU(ID_FORMAT_LINE_SPACING_SINGLE
, MyFrame::OnLineSpacingSingle
)
222 EVT_MENU(ID_FORMAT_LINE_SPACING_DOUBLE
, MyFrame::OnLineSpacingDouble
)
224 EVT_MENU(ID_FORMAT_PARAGRAPH_SPACING_MORE
, MyFrame::OnParagraphSpacingMore
)
225 EVT_MENU(ID_FORMAT_PARAGRAPH_SPACING_LESS
, MyFrame::OnParagraphSpacingLess
)
227 EVT_MENU(ID_VIEW_HTML
, MyFrame::OnViewHTML
)
230 // Create a new application object: this macro will allow wxWidgets to create
231 // the application object during program execution (it's better than using a
232 // static object for many reasons) and also implements the accessor function
233 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
237 // ============================================================================
239 // ============================================================================
241 // ----------------------------------------------------------------------------
242 // the application class
243 // ----------------------------------------------------------------------------
245 // 'Main program' equivalent: the program execution "starts" here
248 m_styleSheet
= new wxRichTextStyleSheet
;
252 // Add extra handlers (plain text is automatically added)
253 wxRichTextBuffer::AddHandler(new wxRichTextXMLHandler
);
254 wxRichTextBuffer::AddHandler(new wxRichTextHTMLHandler
);
256 // Add image handlers
258 wxImage::AddHandler( new wxPNGHandler
);
262 wxImage::AddHandler( new wxJPEGHandler
);
266 wxImage::AddHandler( new wxGIFHandler
);
269 // create the main application window
270 MyFrame
*frame
= new MyFrame(_T("wxRichTextCtrl Sample"), wxID_ANY
, wxDefaultPosition
, wxSize(700, 600));
272 // and show it (the frames, unlike simple controls, are not shown when
273 // created initially)
276 // success: wxApp::OnRun() will be called which will enter the main message
277 // loop and the application will run. If we returned false here, the
278 // application would exit immediately.
288 void MyApp::CreateStyles()
292 wxFont
romanFont(12, wxROMAN
, wxNORMAL
, wxNORMAL
);
293 wxFont
swissFont(12, wxSWISS
, wxNORMAL
, wxNORMAL
);
295 wxRichTextParagraphStyleDefinition
* normalPara
= new wxRichTextParagraphStyleDefinition(wxT("Normal"));
296 wxRichTextAttr normalAttr
;
297 normalAttr
.SetFontFaceName(romanFont
.GetFaceName());
298 normalAttr
.SetFontSize(12);
299 // Let's set all attributes for this style
300 normalAttr
.SetFlags(wxTEXT_ATTR_FONT
| wxTEXT_ATTR_BACKGROUND_COLOUR
| wxTEXT_ATTR_TEXT_COLOUR
|wxTEXT_ATTR_ALIGNMENT
|wxTEXT_ATTR_LEFT_INDENT
|wxTEXT_ATTR_RIGHT_INDENT
|wxTEXT_ATTR_TABS
|
301 wxTEXT_ATTR_PARA_SPACING_BEFORE
|wxTEXT_ATTR_PARA_SPACING_AFTER
|wxTEXT_ATTR_LINE_SPACING
|
302 wxTEXT_ATTR_BULLET_STYLE
|wxTEXT_ATTR_BULLET_NUMBER
);
303 normalPara
->SetStyle(normalAttr
);
305 m_styleSheet
->AddParagraphStyle(normalPara
);
307 wxRichTextParagraphStyleDefinition
* indentedPara
= new wxRichTextParagraphStyleDefinition(wxT("Indented"));
308 wxRichTextAttr indentedAttr
;
309 indentedAttr
.SetFontFaceName(romanFont
.GetFaceName());
310 indentedAttr
.SetFontSize(12);
311 indentedAttr
.SetLeftIndent(100, 0);
312 // We only want to affect indentation
313 indentedAttr
.SetFlags(wxTEXT_ATTR_LEFT_INDENT
|wxTEXT_ATTR_RIGHT_INDENT
);
314 indentedPara
->SetStyle(indentedAttr
);
316 m_styleSheet
->AddParagraphStyle(indentedPara
);
318 wxRichTextParagraphStyleDefinition
* indentedPara2
= new wxRichTextParagraphStyleDefinition(wxT("Red Bold Indented"));
319 wxRichTextAttr indentedAttr2
;
320 indentedAttr2
.SetFontFaceName(romanFont
.GetFaceName());
321 indentedAttr2
.SetFontSize(12);
322 indentedAttr2
.SetFontWeight(wxBOLD
);
323 indentedAttr2
.SetTextColour(*wxRED
);
324 indentedAttr2
.SetFontSize(12);
325 indentedAttr2
.SetLeftIndent(100, 0);
326 // We want to affect indentation, font and text colour
327 indentedAttr2
.SetFlags(wxTEXT_ATTR_LEFT_INDENT
|wxTEXT_ATTR_RIGHT_INDENT
|wxTEXT_ATTR_FONT
|wxTEXT_ATTR_TEXT_COLOUR
);
328 indentedPara2
->SetStyle(indentedAttr2
);
330 m_styleSheet
->AddParagraphStyle(indentedPara2
);
332 wxRichTextParagraphStyleDefinition
* flIndentedPara
= new wxRichTextParagraphStyleDefinition(wxT("First Line Indented"));
333 wxRichTextAttr flIndentedAttr
;
334 flIndentedAttr
.SetFontFaceName(swissFont
.GetFaceName());
335 flIndentedAttr
.SetFontSize(12);
336 flIndentedAttr
.SetLeftIndent(100, -100);
337 // We only want to affect indentation
338 flIndentedAttr
.SetFlags(wxTEXT_ATTR_LEFT_INDENT
|wxTEXT_ATTR_RIGHT_INDENT
);
339 flIndentedPara
->SetStyle(flIndentedAttr
);
341 m_styleSheet
->AddParagraphStyle(flIndentedPara
);
345 wxRichTextCharacterStyleDefinition
* boldDef
= new wxRichTextCharacterStyleDefinition(wxT("Bold"));
346 wxRichTextAttr boldAttr
;
347 boldAttr
.SetFontFaceName(romanFont
.GetFaceName());
348 boldAttr
.SetFontSize(12);
349 boldAttr
.SetFontWeight(wxBOLD
);
350 // We only want to affect boldness
351 boldAttr
.SetFlags(wxTEXT_ATTR_FONT_WEIGHT
);
352 boldDef
->SetStyle(boldAttr
);
354 m_styleSheet
->AddCharacterStyle(boldDef
);
356 wxRichTextCharacterStyleDefinition
* italicDef
= new wxRichTextCharacterStyleDefinition(wxT("Italic"));
357 wxRichTextAttr italicAttr
;
358 italicAttr
.SetFontFaceName(romanFont
.GetFaceName());
359 italicAttr
.SetFontSize(12);
360 italicAttr
.SetFontStyle(wxITALIC
);
361 // We only want to affect italics
362 italicAttr
.SetFlags(wxTEXT_ATTR_FONT_ITALIC
);
363 italicDef
->SetStyle(italicAttr
);
365 m_styleSheet
->AddCharacterStyle(italicDef
);
367 wxRichTextCharacterStyleDefinition
* redDef
= new wxRichTextCharacterStyleDefinition(wxT("Red Bold"));
368 wxRichTextAttr redAttr
;
369 redAttr
.SetFontFaceName(romanFont
.GetFaceName());
370 redAttr
.SetFontSize(12);
371 redAttr
.SetFontWeight(wxBOLD
);
372 redAttr
.SetTextColour(*wxRED
);
373 // We only want to affect colour, weight and face
374 redAttr
.SetFlags(wxTEXT_ATTR_FONT_FACE
|wxTEXT_ATTR_FONT_WEIGHT
|wxTEXT_ATTR_TEXT_COLOUR
);
375 redDef
->SetStyle(redAttr
);
377 m_styleSheet
->AddCharacterStyle(redDef
);
380 // ----------------------------------------------------------------------------
382 // ----------------------------------------------------------------------------
385 MyFrame::MyFrame(const wxString
& title
, wxWindowID id
, const wxPoint
& pos
,
386 const wxSize
& size
, long style
)
387 : wxFrame(NULL
, id
, title
, pos
, size
, style
)
389 // set the frame icon
390 SetIcon(wxICON(sample
));
393 wxMenu
*fileMenu
= new wxMenu
;
395 // the "About" item should be in the help menu
396 wxMenu
*helpMenu
= new wxMenu
;
397 helpMenu
->Append(ID_About
, _T("&About...\tF1"), _T("Show about dialog"));
399 fileMenu
->Append(wxID_OPEN
, _T("&Open\tCtrl+O"), _T("Open a file"));
400 fileMenu
->Append(wxID_SAVE
, _T("&Save\tCtrl+S"), _T("Save a file"));
401 fileMenu
->Append(wxID_SAVEAS
, _T("&Save As...\tF12"), _T("Save to a new file"));
402 fileMenu
->AppendSeparator();
403 fileMenu
->Append(ID_VIEW_HTML
, _T("&View as HTML"), _T("View HTML"));
404 fileMenu
->AppendSeparator();
405 fileMenu
->Append(ID_Quit
, _T("E&xit\tAlt+X"), _T("Quit this program"));
407 wxMenu
* editMenu
= new wxMenu
;
408 editMenu
->Append(wxID_UNDO
, _("&Undo\tCtrl+Z"));
409 editMenu
->Append(wxID_REDO
, _("&Redo\tCtrl+Y"));
410 editMenu
->AppendSeparator();
411 editMenu
->Append(wxID_CUT
, _("Cu&t\tCtrl+X"));
412 editMenu
->Append(wxID_COPY
, _("&Copy\tCtrl+C"));
413 editMenu
->Append(wxID_PASTE
, _("&Paste\tCtrl+V"));
415 editMenu
->Append(wxID_CLEAR
, _("&Delete\tDel"));
417 editMenu
->AppendSeparator();
418 editMenu
->Append(wxID_SELECTALL
, _("Select A&ll\tCtrl+A"));
420 editMenu
->AppendSeparator();
421 editMenu
->Append(wxID_FIND
, _("&Find...\tCtrl+F"));
422 editMenu
->Append(stID_FIND_REPLACE
, _("&Replace...\tCtrl+R"));
425 wxMenu
* formatMenu
= new wxMenu
;
426 formatMenu
->AppendCheckItem(ID_FORMAT_BOLD
, _("&Bold\tCtrl+B"));
427 formatMenu
->AppendCheckItem(ID_FORMAT_ITALIC
, _("&Italic\tCtrl+I"));
428 formatMenu
->AppendCheckItem(ID_FORMAT_UNDERLINE
, _("&Underline\tCtrl+U"));
429 formatMenu
->AppendSeparator();
430 formatMenu
->AppendCheckItem(ID_FORMAT_ALIGN_LEFT
, _("L&eft Align"));
431 formatMenu
->AppendCheckItem(ID_FORMAT_ALIGN_RIGHT
, _("&Right Align"));
432 formatMenu
->AppendCheckItem(ID_FORMAT_ALIGN_CENTRE
, _("&Centre"));
433 formatMenu
->AppendSeparator();
434 formatMenu
->Append(ID_FORMAT_INDENT_MORE
, _("Indent &More"));
435 formatMenu
->Append(ID_FORMAT_INDENT_LESS
, _("Indent &Less"));
436 formatMenu
->AppendSeparator();
437 formatMenu
->Append(ID_FORMAT_PARAGRAPH_SPACING_MORE
, _("Increase Paragraph &Spacing"));
438 formatMenu
->Append(ID_FORMAT_PARAGRAPH_SPACING_LESS
, _("Decrease &Paragraph Spacing"));
439 formatMenu
->AppendSeparator();
440 formatMenu
->Append(ID_FORMAT_LINE_SPACING_SINGLE
, _("Normal Line Spacing"));
441 formatMenu
->Append(ID_FORMAT_LINE_SPACING_HALF
, _("1.5 Line Spacing"));
442 formatMenu
->Append(ID_FORMAT_LINE_SPACING_DOUBLE
, _("Double Line Spacing"));
443 formatMenu
->AppendSeparator();
444 formatMenu
->Append(ID_FORMAT_FONT
, _("&Font..."));
446 // now append the freshly created menu to the menu bar...
447 wxMenuBar
*menuBar
= new wxMenuBar();
448 menuBar
->Append(fileMenu
, _T("&File"));
449 menuBar
->Append(editMenu
, _T("&Edit"));
450 menuBar
->Append(formatMenu
, _T("F&ormat"));
451 menuBar
->Append(helpMenu
, _T("&Help"));
453 // ... and attach this menu bar to the frame
456 // create a status bar just for fun (by default with 1 pane only)
457 // but don't create it on limited screen space (WinCE)
458 bool is_pda
= wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA
;
464 SetStatusText(_T("Welcome to wxRichTextCtrl!"));
468 wxToolBar
* toolBar
= CreateToolBar();
470 toolBar
->AddTool(wxID_OPEN
, wxBitmap(open_xpm
), wxNullBitmap
, false, -1, -1, (wxObject
*) NULL
, _("Open"));
471 toolBar
->AddTool(wxID_SAVEAS
, wxBitmap(save_xpm
), wxNullBitmap
, false, -1, -1, (wxObject
*) NULL
, _("Save"));
472 toolBar
->AddSeparator();
473 toolBar
->AddTool(wxID_CUT
, wxBitmap(cut_xpm
), wxNullBitmap
, false, -1, -1, (wxObject
*) NULL
, _("Cut"));
474 toolBar
->AddTool(wxID_COPY
, wxBitmap(copy_xpm
), wxNullBitmap
, false, -1, -1, (wxObject
*) NULL
, _("Copy"));
475 toolBar
->AddTool(wxID_PASTE
, wxBitmap(paste_xpm
), wxNullBitmap
, false, -1, -1, (wxObject
*) NULL
, _("Paste"));
476 toolBar
->AddSeparator();
477 toolBar
->AddTool(wxID_UNDO
, wxBitmap(undo_xpm
), wxNullBitmap
, false, -1, -1, (wxObject
*) NULL
, _("Undo"));
478 toolBar
->AddTool(wxID_REDO
, wxBitmap(redo_xpm
), wxNullBitmap
, false, -1, -1, (wxObject
*) NULL
, _("Redo"));
479 toolBar
->AddSeparator();
480 toolBar
->AddTool(ID_FORMAT_BOLD
, wxBitmap(bold_xpm
), wxNullBitmap
, true, -1, -1, (wxObject
*) NULL
, _("Bold"));
481 toolBar
->AddTool(ID_FORMAT_ITALIC
, wxBitmap(italic_xpm
), wxNullBitmap
, true, -1, -1, (wxObject
*) NULL
, _("Italic"));
482 toolBar
->AddTool(ID_FORMAT_UNDERLINE
, wxBitmap(underline_xpm
), wxNullBitmap
, true, -1, -1, (wxObject
*) NULL
, _("Underline"));
483 toolBar
->AddSeparator();
484 toolBar
->AddTool(ID_FORMAT_ALIGN_LEFT
, wxBitmap(alignleft_xpm
), wxNullBitmap
, true, -1, -1, (wxObject
*) NULL
, _("Align Left"));
485 toolBar
->AddTool(ID_FORMAT_ALIGN_CENTRE
, wxBitmap(centre_xpm
), wxNullBitmap
, true, -1, -1, (wxObject
*) NULL
, _("Centre"));
486 toolBar
->AddTool(ID_FORMAT_ALIGN_RIGHT
, wxBitmap(alignright_xpm
), wxNullBitmap
, true, -1, -1, (wxObject
*) NULL
, _("Align Right"));
487 toolBar
->AddSeparator();
488 toolBar
->AddTool(ID_FORMAT_INDENT_LESS
, wxBitmap(indentless_xpm
), wxNullBitmap
, false, -1, -1, (wxObject
*) NULL
, _("Indent Less"));
489 toolBar
->AddTool(ID_FORMAT_INDENT_MORE
, wxBitmap(indentmore_xpm
), wxNullBitmap
, false, -1, -1, (wxObject
*) NULL
, _("Indent More"));
490 toolBar
->AddSeparator();
491 toolBar
->AddTool(ID_FORMAT_FONT
, wxBitmap(font_xpm
), wxNullBitmap
, false, -1, -1, (wxObject
*) NULL
, _("Font"));
493 wxRichTextStyleComboCtrl
* combo
= new wxRichTextStyleComboCtrl(toolBar
, wxID_ANY
, wxDefaultPosition
, wxSize(200, -1));
494 toolBar
->AddControl(combo
);
498 wxSplitterWindow
* splitter
= new wxSplitterWindow(this, wxID_ANY
, wxDefaultPosition
, GetClientSize(), wxSP_NO_XP_THEME
|wxSP_3D
|wxSP_LIVE_UPDATE
);
500 wxFont textFont
= wxFont(12, wxROMAN
, wxNORMAL
, wxNORMAL
);
501 wxFont boldFont
= wxFont(12, wxROMAN
, wxNORMAL
, wxBOLD
);
502 wxFont italicFont
= wxFont(12, wxROMAN
, wxITALIC
, wxNORMAL
);
504 m_richTextCtrl
= new wxRichTextCtrl(splitter
, wxID_ANY
, wxEmptyString
, wxDefaultPosition
, wxSize(200, 200), wxVSCROLL
|wxHSCROLL
|wxNO_BORDER
|wxWANTS_CHARS
);
505 wxFont
font(12, wxROMAN
, wxNORMAL
, wxNORMAL
);
507 m_richTextCtrl
->SetFont(font
);
509 combo
->SetStyleSheet(wxGetApp().GetStyleSheet());
510 combo
->SetRichTextCtrl(m_richTextCtrl
);
511 combo
->UpdateStyles();
513 wxRichTextStyleListBox
* styleListBox
= new wxRichTextStyleListBox(splitter
, wxID_ANY
);
515 wxSize display
= wxGetDisplaySize();
516 if ( is_pda
&& ( display
.GetWidth() < display
.GetHeight() ) )
518 splitter
->SplitHorizontally(m_richTextCtrl
, styleListBox
);
522 splitter
->SplitVertically(m_richTextCtrl
, styleListBox
, 500);
525 splitter
->UpdateSize();
527 styleListBox
->SetStyleSheet(wxGetApp().GetStyleSheet());
528 styleListBox
->SetRichTextCtrl(m_richTextCtrl
);
529 styleListBox
->UpdateStyles();
531 wxRichTextCtrl
& r
= *m_richTextCtrl
;
533 r
.BeginSuppressUndo();
535 r
.BeginParagraphSpacing(0, 20);
537 r
.BeginAlignment(wxTEXT_ALIGNMENT_CENTRE
);
541 r
.WriteText(wxT("Welcome to wxRichTextCtrl, a wxWidgets control for editing and presenting styled text and images"));
546 r
.WriteText(wxT("by Julian Smart"));
552 r
.WriteImage(wxBitmap(zebra_xpm
));
559 r
.WriteText(wxT("What can you do with this thing? "));
560 r
.WriteImage(wxBitmap(smiley_xpm
));
561 r
.WriteText(wxT(" Well, you can change text "));
563 r
.BeginTextColour(wxColour(255, 0, 0));
564 r
.WriteText(wxT("colour, like this red bit."));
567 r
.BeginTextColour(wxColour(0, 0, 255));
568 r
.WriteText(wxT(" And this blue bit."));
571 r
.WriteText(wxT(" Naturally you can make things "));
573 r
.WriteText(wxT("bold "));
576 r
.WriteText(wxT("or italic "));
579 r
.WriteText(wxT("or underlined."));
583 r
.WriteText(wxT(" Different font sizes on the same line is allowed, too."));
586 r
.WriteText(wxT(" Next we'll show an indented paragraph."));
588 r
.BeginLeftIndent(60);
591 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."));
596 r
.WriteText(wxT("Next, we'll show a first-line indent, achieved using BeginLeftIndent(100, -40)."));
598 r
.BeginLeftIndent(100, -40);
601 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."));
606 r
.WriteText(wxT("Numbered bullets are possible, again using subindents:"));
608 r
.BeginNumberedBullet(1, 100, 60);
611 r
.WriteText(wxT("This is my first item. Note that wxRichTextCtrl doesn't automatically do numbering, but this will be added later."));
612 r
.EndNumberedBullet();
614 r
.BeginNumberedBullet(2, 100, 60);
617 r
.WriteText(wxT("This is my second item."));
618 r
.EndNumberedBullet();
622 r
.WriteText(wxT("The following paragraph is right-indented:"));
624 r
.BeginRightIndent(200);
627 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."));
632 r
.WriteText(wxT("The following paragraph is right-aligned with 1.5 line spacing:"));
634 r
.BeginAlignment(wxTEXT_ALIGNMENT_RIGHT
);
635 r
.BeginLineSpacing(wxTEXT_ATTR_LINE_SPACING_HALF
);
638 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."));
648 attr
.SetFlags(wxTEXT_ATTR_TABS
);
650 r
.SetDefaultStyle(attr
);
653 r
.WriteText(wxT("This line contains tabs:\tFirst tab\tSecond tab\tThird tab"));
656 r
.WriteText(wxT("Other notable features of wxRichTextCtrl include:"));
658 r
.BeginSymbolBullet(wxT('*'), 100, 60);
660 r
.WriteText(wxT("Compatibility with wxTextCtrl API"));
663 r
.BeginSymbolBullet(wxT('*'), 100, 60);
665 r
.WriteText(wxT("Easy stack-based BeginXXX()...EndXXX() style setting in addition to SetStyle()"));
668 r
.BeginSymbolBullet(wxT('*'), 100, 60);
670 r
.WriteText(wxT("XML loading and saving"));
673 r
.BeginSymbolBullet(wxT('*'), 100, 60);
675 r
.WriteText(wxT("Undo/Redo, with batching option and Undo suppressing"));
678 r
.BeginSymbolBullet(wxT('*'), 100, 60);
680 r
.WriteText(wxT("Clipboard copy and paste"));
683 r
.BeginSymbolBullet(wxT('*'), 100, 60);
685 r
.WriteText(wxT("wxRichTextStyleSheet with named character and paragraph styles, and control for applying named styles"));
688 r
.BeginSymbolBullet(wxT('*'), 100, 60);
690 r
.WriteText(wxT("A design that can easily be extended to other content types, ultimately with text boxes, tables, controls, and so on"));
695 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!"));
697 r
.EndParagraphSpacing();
705 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
707 // true is to force the frame to close
711 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
714 msg
.Printf( _T("This is a demo for wxRichTextCtrl, a control for editing styled text.\n(c) Julian Smart, 2005"));
715 wxMessageBox(msg
, _T("About wxRichTextCtrl Sample"), wxOK
| wxICON_INFORMATION
, this);
718 // Forward command events to the current rich text control, if any
719 bool MyFrame::ProcessEvent(wxEvent
& event
)
721 if (event
.IsCommandEvent() && !event
.IsKindOf(CLASSINFO(wxChildFocusEvent
)))
723 // Problem: we can get infinite recursion because the events
724 // climb back up to this frame, and repeat.
725 // Assume that command events don't cause another command event
726 // to be called, so we can rely on inCommand not being overwritten
728 static int s_eventType
= 0;
729 static wxWindowID s_id
= 0;
731 if (s_id
!= event
.GetId() && s_eventType
!= event
.GetEventType())
733 s_eventType
= event
.GetEventType();
734 s_id
= event
.GetId();
736 wxWindow
* focusWin
= wxFindFocusDescendant(this);
737 if (focusWin
&& focusWin
->ProcessEvent(event
))
754 return wxFrame::ProcessEvent(event
);
757 void MyFrame::OnOpen(wxCommandEvent
& WXUNUSED(event
))
761 wxArrayInt fileTypes
;
763 wxString filter
= wxRichTextBuffer::GetExtWildcard(false, false, & fileTypes
);
766 filter
+= wxT("All files (*.*)|*.*");
768 wxFileDialog
dialog(this,
769 _("Choose a filename"),
775 if (dialog
.ShowModal() == wxID_OK
)
777 wxString path
= dialog
.GetPath();
781 int filterIndex
= dialog
.GetFilterIndex();
782 int fileType
= (filterIndex
< (int) fileTypes
.GetCount())
783 ? fileTypes
[filterIndex
]
784 : wxRICHTEXT_TYPE_TEXT
;
785 m_richTextCtrl
->LoadFile(path
, fileType
);
790 void MyFrame::OnSave(wxCommandEvent
& event
)
792 if (m_richTextCtrl
->GetFilename().empty())
797 m_richTextCtrl
->SaveFile();
800 void MyFrame::OnSaveAs(wxCommandEvent
& WXUNUSED(event
))
802 wxString filter
= wxRichTextBuffer::GetExtWildcard(false, true);
806 wxFileDialog
dialog(this,
807 _("Choose a filename"),
813 if (dialog
.ShowModal() == wxID_OK
)
815 wxString path
= dialog
.GetPath();
819 m_richTextCtrl
->SaveFile(path
);
824 void MyFrame::OnBold(wxCommandEvent
& WXUNUSED(event
))
826 m_richTextCtrl
->ApplyBoldToSelection();
829 void MyFrame::OnItalic(wxCommandEvent
& WXUNUSED(event
))
831 m_richTextCtrl
->ApplyItalicToSelection();
834 void MyFrame::OnUnderline(wxCommandEvent
& WXUNUSED(event
))
836 m_richTextCtrl
->ApplyUnderlineToSelection();
840 void MyFrame::OnUpdateBold(wxUpdateUIEvent
& event
)
842 event
.Check(m_richTextCtrl
->IsSelectionBold());
845 void MyFrame::OnUpdateItalic(wxUpdateUIEvent
& event
)
847 event
.Check(m_richTextCtrl
->IsSelectionItalics());
850 void MyFrame::OnUpdateUnderline(wxUpdateUIEvent
& event
)
852 event
.Check(m_richTextCtrl
->IsSelectionUnderlined());
855 void MyFrame::OnAlignLeft(wxCommandEvent
& WXUNUSED(event
))
857 m_richTextCtrl
->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_LEFT
);
860 void MyFrame::OnAlignCentre(wxCommandEvent
& WXUNUSED(event
))
862 m_richTextCtrl
->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_CENTRE
);
865 void MyFrame::OnAlignRight(wxCommandEvent
& WXUNUSED(event
))
867 m_richTextCtrl
->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_RIGHT
);
870 void MyFrame::OnUpdateAlignLeft(wxUpdateUIEvent
& event
)
872 event
.Check(m_richTextCtrl
->IsSelectionAligned(wxTEXT_ALIGNMENT_LEFT
));
875 void MyFrame::OnUpdateAlignCentre(wxUpdateUIEvent
& event
)
877 event
.Check(m_richTextCtrl
->IsSelectionAligned(wxTEXT_ALIGNMENT_CENTRE
));
880 void MyFrame::OnUpdateAlignRight(wxUpdateUIEvent
& event
)
882 event
.Check(m_richTextCtrl
->IsSelectionAligned(wxTEXT_ALIGNMENT_RIGHT
));
885 void MyFrame::OnFont(wxCommandEvent
& WXUNUSED(event
))
887 if (!m_richTextCtrl
->HasSelection())
890 wxRichTextRange range
= m_richTextCtrl
->GetSelectionRange();
894 attr
.SetFlags(wxTEXT_ATTR_FONT
);
896 if (m_richTextCtrl
->GetStyle(m_richTextCtrl
->GetInsertionPoint(), attr
))
897 fontData
.SetInitialFont(attr
.GetFont());
899 wxFontDialog
dialog(this, fontData
);
900 if (dialog
.ShowModal() == wxID_OK
)
902 fontData
= dialog
.GetFontData();
903 attr
.SetFlags(wxTEXT_ATTR_FONT
);
904 attr
.SetFont(fontData
.GetChosenFont());
905 if (attr
.GetFont().Ok())
907 m_richTextCtrl
->SetStyle(range
, attr
);
912 void MyFrame::OnIndentMore(wxCommandEvent
& WXUNUSED(event
))
915 attr
.SetFlags(wxTEXT_ATTR_LEFT_INDENT
);
917 if (m_richTextCtrl
->GetStyle(m_richTextCtrl
->GetInsertionPoint(), attr
))
919 wxRichTextRange
range(m_richTextCtrl
->GetInsertionPoint(), m_richTextCtrl
->GetInsertionPoint());
920 if (m_richTextCtrl
->HasSelection())
921 range
= m_richTextCtrl
->GetSelectionRange();
924 attr
.SetLeftIndent(attr
.GetLeftIndent() + 100);
926 attr
.SetFlags(wxTEXT_ATTR_LEFT_INDENT
);
927 m_richTextCtrl
->SetStyle(range
, attr
);
931 void MyFrame::OnIndentLess(wxCommandEvent
& WXUNUSED(event
))
934 attr
.SetFlags(wxTEXT_ATTR_LEFT_INDENT
);
936 if (m_richTextCtrl
->GetStyle(m_richTextCtrl
->GetInsertionPoint(), attr
))
938 wxRichTextRange
range(m_richTextCtrl
->GetInsertionPoint(), m_richTextCtrl
->GetInsertionPoint());
939 if (m_richTextCtrl
->HasSelection())
940 range
= m_richTextCtrl
->GetSelectionRange();
942 if (attr
.GetLeftIndent() >= 100)
945 attr
.SetLeftIndent(attr
.GetLeftIndent() - 100);
947 m_richTextCtrl
->SetStyle(range
, attr
);
952 void MyFrame::OnLineSpacingHalf(wxCommandEvent
& WXUNUSED(event
))
955 attr
.SetFlags(wxTEXT_ATTR_LINE_SPACING
);
957 if (m_richTextCtrl
->GetStyle(m_richTextCtrl
->GetInsertionPoint(), attr
))
959 wxRichTextRange
range(m_richTextCtrl
->GetInsertionPoint(), m_richTextCtrl
->GetInsertionPoint());
960 if (m_richTextCtrl
->HasSelection())
961 range
= m_richTextCtrl
->GetSelectionRange();
964 attr
.SetFlags(wxTEXT_ATTR_LINE_SPACING
);
965 attr
.SetLineSpacing(15);
967 m_richTextCtrl
->SetStyle(range
, attr
);
971 void MyFrame::OnLineSpacingDouble(wxCommandEvent
& WXUNUSED(event
))
974 attr
.SetFlags(wxTEXT_ATTR_LINE_SPACING
);
976 if (m_richTextCtrl
->GetStyle(m_richTextCtrl
->GetInsertionPoint(), attr
))
978 wxRichTextRange
range(m_richTextCtrl
->GetInsertionPoint(), m_richTextCtrl
->GetInsertionPoint());
979 if (m_richTextCtrl
->HasSelection())
980 range
= m_richTextCtrl
->GetSelectionRange();
983 attr
.SetFlags(wxTEXT_ATTR_LINE_SPACING
);
984 attr
.SetLineSpacing(20);
986 m_richTextCtrl
->SetStyle(range
, attr
);
990 void MyFrame::OnLineSpacingSingle(wxCommandEvent
& WXUNUSED(event
))
993 attr
.SetFlags(wxTEXT_ATTR_LINE_SPACING
);
995 if (m_richTextCtrl
->GetStyle(m_richTextCtrl
->GetInsertionPoint(), attr
))
997 wxRichTextRange
range(m_richTextCtrl
->GetInsertionPoint(), m_richTextCtrl
->GetInsertionPoint());
998 if (m_richTextCtrl
->HasSelection())
999 range
= m_richTextCtrl
->GetSelectionRange();
1001 wxFontData fontData
;
1002 attr
.SetFlags(wxTEXT_ATTR_LINE_SPACING
);
1003 attr
.SetLineSpacing(0); // Can also use 10
1005 m_richTextCtrl
->SetStyle(range
, attr
);
1009 void MyFrame::OnParagraphSpacingMore(wxCommandEvent
& WXUNUSED(event
))
1012 attr
.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER
);
1014 if (m_richTextCtrl
->GetStyle(m_richTextCtrl
->GetInsertionPoint(), attr
))
1016 wxRichTextRange
range(m_richTextCtrl
->GetInsertionPoint(), m_richTextCtrl
->GetInsertionPoint());
1017 if (m_richTextCtrl
->HasSelection())
1018 range
= m_richTextCtrl
->GetSelectionRange();
1020 wxFontData fontData
;
1021 attr
.SetParagraphSpacingAfter(attr
.GetParagraphSpacingAfter() + 20);
1023 attr
.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER
);
1024 m_richTextCtrl
->SetStyle(range
, attr
);
1028 void MyFrame::OnParagraphSpacingLess(wxCommandEvent
& WXUNUSED(event
))
1031 attr
.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER
);
1033 if (m_richTextCtrl
->GetStyle(m_richTextCtrl
->GetInsertionPoint(), attr
))
1035 wxRichTextRange
range(m_richTextCtrl
->GetInsertionPoint(), m_richTextCtrl
->GetInsertionPoint());
1036 if (m_richTextCtrl
->HasSelection())
1037 range
= m_richTextCtrl
->GetSelectionRange();
1039 if (attr
.GetParagraphSpacingAfter() >= 20)
1041 wxFontData fontData
;
1042 attr
.SetParagraphSpacingAfter(attr
.GetParagraphSpacingAfter() - 20);
1044 attr
.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER
);
1045 m_richTextCtrl
->SetStyle(range
, attr
);
1050 void MyFrame::OnViewHTML(wxCommandEvent
& WXUNUSED(event
))
1052 wxDialog
dialog(this, wxID_ANY
, _("HTML"), wxDefaultPosition
, wxSize(500, 400), wxDEFAULT_DIALOG_STYLE
);
1054 wxBoxSizer
* boxSizer
= new wxBoxSizer(wxVERTICAL
);
1055 dialog
.SetSizer(boxSizer
);
1057 wxHtmlWindow
* win
= new wxHtmlWindow(& dialog
, wxID_ANY
, wxDefaultPosition
, wxSize(500, 400), wxSUNKEN_BORDER
);
1058 boxSizer
->Add(win
, 1, wxALL
, 5);
1060 wxButton
* cancelButton
= new wxButton(& dialog
, wxID_CANCEL
, wxT("&Close"));
1061 boxSizer
->Add(cancelButton
, 0, wxALL
|wxCENTRE
, 5);
1064 wxStringOutputStream
strStream(& text
);
1066 wxRichTextHTMLHandler htmlHandler
;
1067 if (htmlHandler
.SaveFile(& m_richTextCtrl
->GetBuffer(), strStream
))
1072 boxSizer
->Fit(& dialog
);