Applied patch #13534: wxRichTextCtrl: Make it easier to use TextEffects flags
[wxWidgets.git] / samples / richtext / richtext.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: samples/richtext/richtext.cpp
3 // Purpose: wxWidgets rich text editor sample
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 2005-10-02
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx/wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 // for all others, include the necessary headers (this file is usually all you
28 // need because it includes almost all "standard" wxWidgets headers)
29 #ifndef WX_PRECOMP
30 #include "wx/wx.h"
31 #endif
32
33 #include "wx/fontdlg.h"
34 #include "wx/splitter.h"
35 #include "wx/sstream.h"
36 #include "wx/html/htmlwin.h"
37 #include "wx/stopwatch.h"
38
39 #if wxUSE_FILESYSTEM
40 #include "wx/filesys.h"
41 #include "wx/fs_mem.h"
42 #endif
43
44 #if wxUSE_HELP
45 #include "wx/cshelp.h"
46 #endif
47
48 #ifndef __WXMSW__
49 #include "../sample.xpm"
50 #endif
51
52 #include "bitmaps/smiley.xpm"
53 // #include "bitmaps/idea.xpm"
54 #include "bitmaps/zebra.xpm"
55
56 #include "bitmaps/open.xpm"
57 #include "bitmaps/save.xpm"
58 #include "bitmaps/copy.xpm"
59 #include "bitmaps/cut.xpm"
60 #include "bitmaps/paste.xpm"
61 #include "bitmaps/undo.xpm"
62 #include "bitmaps/redo.xpm"
63 #include "bitmaps/bold.xpm"
64 #include "bitmaps/italic.xpm"
65 #include "bitmaps/underline.xpm"
66
67 #include "bitmaps/alignleft.xpm"
68 #include "bitmaps/alignright.xpm"
69 #include "bitmaps/centre.xpm"
70 #include "bitmaps/font.xpm"
71 #include "bitmaps/indentless.xpm"
72 #include "bitmaps/indentmore.xpm"
73
74 #include "wx/richtext/richtextctrl.h"
75 #include "wx/richtext/richtextstyles.h"
76 #include "wx/richtext/richtextxml.h"
77 #include "wx/richtext/richtexthtml.h"
78 #include "wx/richtext/richtextformatdlg.h"
79 #include "wx/richtext/richtextsymboldlg.h"
80 #include "wx/richtext/richtextstyledlg.h"
81 #include "wx/richtext/richtextprint.h"
82 #include "wx/richtext/richtextimagedlg.h"
83
84 // ----------------------------------------------------------------------------
85 // resources
86 // ----------------------------------------------------------------------------
87
88 // ----------------------------------------------------------------------------
89 // private classes
90 // ----------------------------------------------------------------------------
91
92 // Define a new application type, each program should derive a class from wxApp
93 class MyApp : public wxApp
94 {
95 public:
96 // override base class virtuals
97 // ----------------------------
98
99 // this one is called on application startup and is a good place for the app
100 // initialization (doing it here and not in the ctor allows to have an error
101 // return: if OnInit() returns false, the application terminates)
102 virtual bool OnInit();
103 virtual int OnExit();
104
105 void CreateStyles();
106
107 wxRichTextStyleSheet* GetStyleSheet() const { return m_styleSheet; }
108 wxRichTextPrinting* GetPrinting() const { return m_printing; }
109
110 wxRichTextStyleSheet* m_styleSheet;
111 wxRichTextPrinting* m_printing;
112 };
113
114 // Define a new frame type: this is going to be our main frame
115 class MyFrame : public wxFrame
116 {
117 public:
118 // ctor(s)
119 MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos = wxDefaultPosition,
120 const wxSize& size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE);
121
122 // event handlers (these functions should _not_ be virtual)
123 void OnQuit(wxCommandEvent& event);
124 void OnAbout(wxCommandEvent& event);
125
126 void OnOpen(wxCommandEvent& event);
127 void OnSave(wxCommandEvent& event);
128 void OnSaveAs(wxCommandEvent& event);
129
130 void OnBold(wxCommandEvent& event);
131 void OnItalic(wxCommandEvent& event);
132 void OnUnderline(wxCommandEvent& event);
133
134 void OnStrikethrough(wxCommandEvent& event);
135 void OnSuperscript(wxCommandEvent& event);
136 void OnSubscript(wxCommandEvent& event);
137
138 void OnUpdateBold(wxUpdateUIEvent& event);
139 void OnUpdateItalic(wxUpdateUIEvent& event);
140 void OnUpdateUnderline(wxUpdateUIEvent& event);
141 void OnUpdateStrikethrough(wxUpdateUIEvent& event);
142 void OnUpdateSuperscript(wxUpdateUIEvent& event);
143 void OnUpdateSubscript(wxUpdateUIEvent& event);
144
145 void OnAlignLeft(wxCommandEvent& event);
146 void OnAlignCentre(wxCommandEvent& event);
147 void OnAlignRight(wxCommandEvent& event);
148
149 void OnUpdateAlignLeft(wxUpdateUIEvent& event);
150 void OnUpdateAlignCentre(wxUpdateUIEvent& event);
151 void OnUpdateAlignRight(wxUpdateUIEvent& event);
152
153 void OnIndentMore(wxCommandEvent& event);
154 void OnIndentLess(wxCommandEvent& event);
155
156 void OnFont(wxCommandEvent& event);
157 void OnImage(wxCommandEvent& event);
158 void OnUpdateImage(wxUpdateUIEvent& event);
159 void OnParagraph(wxCommandEvent& event);
160 void OnFormat(wxCommandEvent& event);
161 void OnUpdateFormat(wxUpdateUIEvent& event);
162
163 void OnInsertSymbol(wxCommandEvent& event);
164
165 void OnLineSpacingHalf(wxCommandEvent& event);
166 void OnLineSpacingDouble(wxCommandEvent& event);
167 void OnLineSpacingSingle(wxCommandEvent& event);
168
169 void OnParagraphSpacingMore(wxCommandEvent& event);
170 void OnParagraphSpacingLess(wxCommandEvent& event);
171
172 void OnNumberList(wxCommandEvent& event);
173 void OnBulletsAndNumbering(wxCommandEvent& event);
174 void OnItemizeList(wxCommandEvent& event);
175 void OnRenumberList(wxCommandEvent& event);
176 void OnPromoteList(wxCommandEvent& event);
177 void OnDemoteList(wxCommandEvent& event);
178 void OnClearList(wxCommandEvent& event);
179
180 void OnReload(wxCommandEvent& event);
181
182 void OnViewHTML(wxCommandEvent& event);
183
184 void OnSwitchStyleSheets(wxCommandEvent& event);
185 void OnManageStyles(wxCommandEvent& event);
186
187 void OnInsertURL(wxCommandEvent& event);
188 void OnURL(wxTextUrlEvent& event);
189 void OnStyleSheetReplacing(wxRichTextEvent& event);
190
191 void OnPrint(wxCommandEvent& event);
192 void OnPreview(wxCommandEvent& event);
193 void OnPageSetup(wxCommandEvent& event);
194
195 void OnInsertImage(wxCommandEvent& event);
196 protected:
197
198 // Forward command events to the current rich text control, if any
199 bool ProcessEvent(wxEvent& event);
200
201 // Write text
202 void WriteInitialText();
203
204 private:
205 // any class wishing to process wxWidgets events must use this macro
206 DECLARE_EVENT_TABLE()
207
208 wxRichTextCtrl* m_richTextCtrl;
209 };
210
211 // ----------------------------------------------------------------------------
212 // constants
213 // ----------------------------------------------------------------------------
214
215 // IDs for the controls and the menu commands
216 enum
217 {
218 // menu items
219 ID_Quit = wxID_EXIT,
220 ID_About = wxID_ABOUT,
221
222 ID_FORMAT_BOLD = 100,
223 ID_FORMAT_ITALIC,
224 ID_FORMAT_UNDERLINE,
225 ID_FORMAT_STRIKETHROUGH,
226 ID_FORMAT_SUPERSCRIPT,
227 ID_FORMAT_SUBSCRIPT,
228 ID_FORMAT_FONT,
229 ID_FORMAT_IMAGE,
230 ID_FORMAT_PARAGRAPH,
231 ID_FORMAT_CONTENT,
232
233 ID_RELOAD,
234
235 ID_INSERT_SYMBOL,
236 ID_INSERT_URL,
237 ID_INSERT_IMAGE,
238
239 ID_FORMAT_ALIGN_LEFT,
240 ID_FORMAT_ALIGN_CENTRE,
241 ID_FORMAT_ALIGN_RIGHT,
242
243 ID_FORMAT_INDENT_MORE,
244 ID_FORMAT_INDENT_LESS,
245
246 ID_FORMAT_PARAGRAPH_SPACING_MORE,
247 ID_FORMAT_PARAGRAPH_SPACING_LESS,
248
249 ID_FORMAT_LINE_SPACING_HALF,
250 ID_FORMAT_LINE_SPACING_DOUBLE,
251 ID_FORMAT_LINE_SPACING_SINGLE,
252
253 ID_FORMAT_NUMBER_LIST,
254 ID_FORMAT_BULLETS_AND_NUMBERING,
255 ID_FORMAT_ITEMIZE_LIST,
256 ID_FORMAT_RENUMBER_LIST,
257 ID_FORMAT_PROMOTE_LIST,
258 ID_FORMAT_DEMOTE_LIST,
259 ID_FORMAT_CLEAR_LIST,
260
261 ID_VIEW_HTML,
262 ID_SWITCH_STYLE_SHEETS,
263 ID_MANAGE_STYLES,
264
265 ID_PRINT,
266 ID_PREVIEW,
267 ID_PAGE_SETUP,
268
269 ID_RICHTEXT_CTRL,
270 ID_RICHTEXT_STYLE_LIST,
271 ID_RICHTEXT_STYLE_COMBO
272 };
273
274 // ----------------------------------------------------------------------------
275 // event tables and other macros for wxWidgets
276 // ----------------------------------------------------------------------------
277
278 // the event tables connect the wxWidgets events with the functions (event
279 // handlers) which process them. It can be also done at run-time, but for the
280 // simple menu events like this the static method is much simpler.
281 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
282 EVT_MENU(ID_Quit, MyFrame::OnQuit)
283 EVT_MENU(ID_About, MyFrame::OnAbout)
284
285 EVT_MENU(wxID_OPEN, MyFrame::OnOpen)
286 EVT_MENU(wxID_SAVE, MyFrame::OnSave)
287 EVT_MENU(wxID_SAVEAS, MyFrame::OnSaveAs)
288
289 EVT_MENU(ID_FORMAT_BOLD, MyFrame::OnBold)
290 EVT_MENU(ID_FORMAT_ITALIC, MyFrame::OnItalic)
291 EVT_MENU(ID_FORMAT_UNDERLINE, MyFrame::OnUnderline)
292
293 EVT_MENU(ID_FORMAT_STRIKETHROUGH, MyFrame::OnStrikethrough)
294 EVT_MENU(ID_FORMAT_SUPERSCRIPT, MyFrame::OnSuperscript)
295 EVT_MENU(ID_FORMAT_SUBSCRIPT, MyFrame::OnSubscript)
296
297 EVT_UPDATE_UI(ID_FORMAT_BOLD, MyFrame::OnUpdateBold)
298 EVT_UPDATE_UI(ID_FORMAT_ITALIC, MyFrame::OnUpdateItalic)
299 EVT_UPDATE_UI(ID_FORMAT_UNDERLINE, MyFrame::OnUpdateUnderline)
300
301 EVT_UPDATE_UI(ID_FORMAT_STRIKETHROUGH, MyFrame::OnUpdateStrikethrough)
302 EVT_UPDATE_UI(ID_FORMAT_SUPERSCRIPT, MyFrame::OnUpdateSuperscript)
303 EVT_UPDATE_UI(ID_FORMAT_SUBSCRIPT, MyFrame::OnUpdateSubscript)
304
305 EVT_MENU(ID_FORMAT_ALIGN_LEFT, MyFrame::OnAlignLeft)
306 EVT_MENU(ID_FORMAT_ALIGN_CENTRE, MyFrame::OnAlignCentre)
307 EVT_MENU(ID_FORMAT_ALIGN_RIGHT, MyFrame::OnAlignRight)
308
309 EVT_UPDATE_UI(ID_FORMAT_ALIGN_LEFT, MyFrame::OnUpdateAlignLeft)
310 EVT_UPDATE_UI(ID_FORMAT_ALIGN_CENTRE, MyFrame::OnUpdateAlignCentre)
311 EVT_UPDATE_UI(ID_FORMAT_ALIGN_RIGHT, MyFrame::OnUpdateAlignRight)
312
313 EVT_MENU(ID_FORMAT_FONT, MyFrame::OnFont)
314 EVT_MENU(ID_FORMAT_IMAGE, MyFrame::OnImage)
315 EVT_MENU(ID_FORMAT_PARAGRAPH, MyFrame::OnParagraph)
316 EVT_MENU(ID_FORMAT_CONTENT, MyFrame::OnFormat)
317 EVT_UPDATE_UI(ID_FORMAT_CONTENT, MyFrame::OnUpdateFormat)
318 EVT_UPDATE_UI(ID_FORMAT_FONT, MyFrame::OnUpdateFormat)
319 EVT_UPDATE_UI(ID_FORMAT_IMAGE, MyFrame::OnUpdateImage)
320 EVT_UPDATE_UI(ID_FORMAT_PARAGRAPH, MyFrame::OnUpdateFormat)
321 EVT_MENU(ID_FORMAT_INDENT_MORE, MyFrame::OnIndentMore)
322 EVT_MENU(ID_FORMAT_INDENT_LESS, MyFrame::OnIndentLess)
323
324 EVT_MENU(ID_FORMAT_LINE_SPACING_HALF, MyFrame::OnLineSpacingHalf)
325 EVT_MENU(ID_FORMAT_LINE_SPACING_SINGLE, MyFrame::OnLineSpacingSingle)
326 EVT_MENU(ID_FORMAT_LINE_SPACING_DOUBLE, MyFrame::OnLineSpacingDouble)
327
328 EVT_MENU(ID_FORMAT_PARAGRAPH_SPACING_MORE, MyFrame::OnParagraphSpacingMore)
329 EVT_MENU(ID_FORMAT_PARAGRAPH_SPACING_LESS, MyFrame::OnParagraphSpacingLess)
330
331 EVT_MENU(ID_RELOAD, MyFrame::OnReload)
332
333 EVT_MENU(ID_INSERT_SYMBOL, MyFrame::OnInsertSymbol)
334 EVT_MENU(ID_INSERT_URL, MyFrame::OnInsertURL)
335 EVT_MENU(ID_INSERT_IMAGE, MyFrame::OnInsertImage)
336
337 EVT_MENU(ID_FORMAT_NUMBER_LIST, MyFrame::OnNumberList)
338 EVT_MENU(ID_FORMAT_BULLETS_AND_NUMBERING, MyFrame::OnBulletsAndNumbering)
339 EVT_MENU(ID_FORMAT_ITEMIZE_LIST, MyFrame::OnItemizeList)
340 EVT_MENU(ID_FORMAT_RENUMBER_LIST, MyFrame::OnRenumberList)
341 EVT_MENU(ID_FORMAT_PROMOTE_LIST, MyFrame::OnPromoteList)
342 EVT_MENU(ID_FORMAT_DEMOTE_LIST, MyFrame::OnDemoteList)
343 EVT_MENU(ID_FORMAT_CLEAR_LIST, MyFrame::OnClearList)
344
345 EVT_MENU(ID_VIEW_HTML, MyFrame::OnViewHTML)
346 EVT_MENU(ID_SWITCH_STYLE_SHEETS, MyFrame::OnSwitchStyleSheets)
347 EVT_MENU(ID_MANAGE_STYLES, MyFrame::OnManageStyles)
348
349 EVT_MENU(ID_PRINT, MyFrame::OnPrint)
350 EVT_MENU(ID_PREVIEW, MyFrame::OnPreview)
351 EVT_MENU(ID_PAGE_SETUP, MyFrame::OnPageSetup)
352
353 EVT_TEXT_URL(wxID_ANY, MyFrame::OnURL)
354 EVT_RICHTEXT_STYLESHEET_REPLACING(wxID_ANY, MyFrame::OnStyleSheetReplacing)
355 END_EVENT_TABLE()
356
357 // Create a new application object: this macro will allow wxWidgets to create
358 // the application object during program execution (it's better than using a
359 // static object for many reasons) and also implements the accessor function
360 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
361 // not wxApp)
362 IMPLEMENT_APP(MyApp)
363
364 // ============================================================================
365 // implementation
366 // ============================================================================
367
368 // ----------------------------------------------------------------------------
369 // the application class
370 // ----------------------------------------------------------------------------
371
372 // 'Main program' equivalent: the program execution "starts" here
373 bool MyApp::OnInit()
374 {
375 if ( !wxApp::OnInit() )
376 return false;
377
378 #if wxUSE_HELP
379 wxHelpProvider::Set(new wxSimpleHelpProvider);
380 #endif
381
382 m_styleSheet = new wxRichTextStyleSheet;
383 m_printing = new wxRichTextPrinting(wxT("Test Document"));
384
385 m_printing->SetFooterText(wxT("@TITLE@"), wxRICHTEXT_PAGE_ALL, wxRICHTEXT_PAGE_CENTRE);
386 m_printing->SetFooterText(wxT("Page @PAGENUM@"), wxRICHTEXT_PAGE_ALL, wxRICHTEXT_PAGE_RIGHT);
387
388 CreateStyles();
389
390 // Add extra handlers (plain text is automatically added)
391 wxRichTextBuffer::AddHandler(new wxRichTextXMLHandler);
392 wxRichTextBuffer::AddHandler(new wxRichTextHTMLHandler);
393
394 // Add image handlers
395 #if wxUSE_LIBPNG
396 wxImage::AddHandler( new wxPNGHandler );
397 #endif
398
399 #if wxUSE_LIBJPEG
400 wxImage::AddHandler( new wxJPEGHandler );
401 #endif
402
403 #if wxUSE_GIF
404 wxImage::AddHandler( new wxGIFHandler );
405 #endif
406
407 #if wxUSE_FILESYSTEM
408 wxFileSystem::AddHandler( new wxMemoryFSHandler );
409 #endif
410
411 // create the main application window
412 MyFrame *frame = new MyFrame(wxT("wxRichTextCtrl Sample"), wxID_ANY, wxDefaultPosition, wxSize(700, 600));
413
414 m_printing->SetParentWindow(frame);
415
416 // and show it (the frames, unlike simple controls, are not shown when
417 // created initially)
418 frame->Show(true);
419
420 // success: wxApp::OnRun() will be called which will enter the main message
421 // loop and the application will run. If we returned false here, the
422 // application would exit immediately.
423 return true;
424 }
425
426 int MyApp::OnExit()
427 {
428 delete m_printing;
429 delete m_styleSheet;
430
431 return 0;
432 }
433
434 void MyApp::CreateStyles()
435 {
436 // Paragraph styles
437
438 wxFont romanFont(12, wxROMAN, wxNORMAL, wxNORMAL);
439 wxFont swissFont(12, wxSWISS, wxNORMAL, wxNORMAL);
440
441 wxRichTextParagraphStyleDefinition* normalPara = new wxRichTextParagraphStyleDefinition(wxT("Normal"));
442 wxRichTextAttr normalAttr;
443 normalAttr.SetFontFaceName(romanFont.GetFaceName());
444 normalAttr.SetFontSize(12);
445 // Let's set all attributes for this style
446 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|
447 wxTEXT_ATTR_PARA_SPACING_BEFORE|wxTEXT_ATTR_PARA_SPACING_AFTER|wxTEXT_ATTR_LINE_SPACING|
448 wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER);
449 normalPara->SetStyle(normalAttr);
450
451 m_styleSheet->AddParagraphStyle(normalPara);
452
453 wxRichTextParagraphStyleDefinition* indentedPara = new wxRichTextParagraphStyleDefinition(wxT("Indented"));
454 wxRichTextAttr indentedAttr;
455 indentedAttr.SetFontFaceName(romanFont.GetFaceName());
456 indentedAttr.SetFontSize(12);
457 indentedAttr.SetLeftIndent(100, 0);
458 // We only want to affect indentation
459 indentedAttr.SetFlags(wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT);
460 indentedPara->SetStyle(indentedAttr);
461
462 m_styleSheet->AddParagraphStyle(indentedPara);
463
464 wxRichTextParagraphStyleDefinition* indentedPara2 = new wxRichTextParagraphStyleDefinition(wxT("Red Bold Indented"));
465 wxRichTextAttr indentedAttr2;
466 indentedAttr2.SetFontFaceName(romanFont.GetFaceName());
467 indentedAttr2.SetFontSize(12);
468 indentedAttr2.SetFontWeight(wxFONTWEIGHT_BOLD);
469 indentedAttr2.SetTextColour(*wxRED);
470 indentedAttr2.SetFontSize(12);
471 indentedAttr2.SetLeftIndent(100, 0);
472 // We want to affect indentation, font and text colour
473 indentedAttr2.SetFlags(wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT|wxTEXT_ATTR_FONT|wxTEXT_ATTR_TEXT_COLOUR);
474 indentedPara2->SetStyle(indentedAttr2);
475
476 m_styleSheet->AddParagraphStyle(indentedPara2);
477
478 wxRichTextParagraphStyleDefinition* flIndentedPara = new wxRichTextParagraphStyleDefinition(wxT("First Line Indented"));
479 wxRichTextAttr flIndentedAttr;
480 flIndentedAttr.SetFontFaceName(swissFont.GetFaceName());
481 flIndentedAttr.SetFontSize(12);
482 flIndentedAttr.SetLeftIndent(100, -100);
483 // We only want to affect indentation
484 flIndentedAttr.SetFlags(wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT);
485 flIndentedPara->SetStyle(flIndentedAttr);
486
487 m_styleSheet->AddParagraphStyle(flIndentedPara);
488
489 // Character styles
490
491 wxRichTextCharacterStyleDefinition* boldDef = new wxRichTextCharacterStyleDefinition(wxT("Bold"));
492 wxRichTextAttr boldAttr;
493 boldAttr.SetFontFaceName(romanFont.GetFaceName());
494 boldAttr.SetFontSize(12);
495 boldAttr.SetFontWeight(wxFONTWEIGHT_BOLD);
496 // We only want to affect boldness
497 boldAttr.SetFlags(wxTEXT_ATTR_FONT_WEIGHT);
498 boldDef->SetStyle(boldAttr);
499
500 m_styleSheet->AddCharacterStyle(boldDef);
501
502 wxRichTextCharacterStyleDefinition* italicDef = new wxRichTextCharacterStyleDefinition(wxT("Italic"));
503 wxRichTextAttr italicAttr;
504 italicAttr.SetFontFaceName(romanFont.GetFaceName());
505 italicAttr.SetFontSize(12);
506 italicAttr.SetFontStyle(wxFONTSTYLE_ITALIC);
507 // We only want to affect italics
508 italicAttr.SetFlags(wxTEXT_ATTR_FONT_ITALIC);
509 italicDef->SetStyle(italicAttr);
510
511 m_styleSheet->AddCharacterStyle(italicDef);
512
513 wxRichTextCharacterStyleDefinition* redDef = new wxRichTextCharacterStyleDefinition(wxT("Red Bold"));
514 wxRichTextAttr redAttr;
515 redAttr.SetFontFaceName(romanFont.GetFaceName());
516 redAttr.SetFontSize(12);
517 redAttr.SetFontWeight(wxFONTWEIGHT_BOLD);
518 redAttr.SetTextColour(*wxRED);
519 // We only want to affect colour, weight and face
520 redAttr.SetFlags(wxTEXT_ATTR_FONT_FACE|wxTEXT_ATTR_FONT_WEIGHT|wxTEXT_ATTR_TEXT_COLOUR);
521 redDef->SetStyle(redAttr);
522
523 m_styleSheet->AddCharacterStyle(redDef);
524
525 wxRichTextListStyleDefinition* bulletList = new wxRichTextListStyleDefinition(wxT("Bullet List 1"));
526 int i;
527 for (i = 0; i < 10; i++)
528 {
529 wxString bulletText;
530 if (i == 0)
531 bulletText = wxT("standard/circle");
532 else if (i == 1)
533 bulletText = wxT("standard/square");
534 else if (i == 2)
535 bulletText = wxT("standard/circle");
536 else if (i == 3)
537 bulletText = wxT("standard/square");
538 else
539 bulletText = wxT("standard/circle");
540
541 bulletList->SetAttributes(i, (i+1)*60, 60, wxTEXT_ATTR_BULLET_STYLE_STANDARD, bulletText);
542 }
543
544 m_styleSheet->AddListStyle(bulletList);
545
546 wxRichTextListStyleDefinition* numberedList = new wxRichTextListStyleDefinition(wxT("Numbered List 1"));
547 for (i = 0; i < 10; i++)
548 {
549 long numberStyle;
550 if (i == 0)
551 numberStyle = wxTEXT_ATTR_BULLET_STYLE_ARABIC|wxTEXT_ATTR_BULLET_STYLE_PERIOD;
552 else if (i == 1)
553 numberStyle = wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER|wxTEXT_ATTR_BULLET_STYLE_PARENTHESES;
554 else if (i == 2)
555 numberStyle = wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER|wxTEXT_ATTR_BULLET_STYLE_PARENTHESES;
556 else if (i == 3)
557 numberStyle = wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER|wxTEXT_ATTR_BULLET_STYLE_PARENTHESES;
558 else
559 numberStyle = wxTEXT_ATTR_BULLET_STYLE_ARABIC|wxTEXT_ATTR_BULLET_STYLE_PERIOD;
560
561 numberStyle |= wxTEXT_ATTR_BULLET_STYLE_ALIGN_RIGHT;
562
563 numberedList->SetAttributes(i, (i+1)*60, 60, numberStyle);
564 }
565
566 m_styleSheet->AddListStyle(numberedList);
567
568 wxRichTextListStyleDefinition* outlineList = new wxRichTextListStyleDefinition(wxT("Outline List 1"));
569 for (i = 0; i < 10; i++)
570 {
571 long numberStyle;
572 if (i < 4)
573 numberStyle = wxTEXT_ATTR_BULLET_STYLE_OUTLINE|wxTEXT_ATTR_BULLET_STYLE_PERIOD;
574 else
575 numberStyle = wxTEXT_ATTR_BULLET_STYLE_ARABIC|wxTEXT_ATTR_BULLET_STYLE_PERIOD;
576
577 outlineList->SetAttributes(i, (i+1)*120, 120, numberStyle);
578 }
579
580 m_styleSheet->AddListStyle(outlineList);
581 }
582
583 // ----------------------------------------------------------------------------
584 // main frame
585 // ----------------------------------------------------------------------------
586
587 // frame constructor
588 MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
589 const wxSize& size, long style)
590 : wxFrame(NULL, id, title, pos, size, style)
591 {
592 // set the frame icon
593 SetIcon(wxICON(sample));
594
595 // create a menu bar
596 wxMenu *fileMenu = new wxMenu;
597
598 // the "About" item should be in the help menu
599 wxMenu *helpMenu = new wxMenu;
600 helpMenu->Append(ID_About, wxT("&About...\tF1"), wxT("Show about dialog"));
601
602 fileMenu->Append(wxID_OPEN, wxT("&Open\tCtrl+O"), wxT("Open a file"));
603 fileMenu->Append(wxID_SAVE, wxT("&Save\tCtrl+S"), wxT("Save a file"));
604 fileMenu->Append(wxID_SAVEAS, wxT("&Save As...\tF12"), wxT("Save to a new file"));
605 fileMenu->AppendSeparator();
606 fileMenu->Append(ID_RELOAD, wxT("&Reload Text\tF2"), wxT("Reload the initial text"));
607 fileMenu->AppendSeparator();
608 fileMenu->Append(ID_PAGE_SETUP, wxT("Page Set&up..."), wxT("Page setup"));
609 fileMenu->Append(ID_PRINT, wxT("&Print...\tCtrl+P"), wxT("Print"));
610 fileMenu->Append(ID_PREVIEW, wxT("Print Pre&view"), wxT("Print preview"));
611 fileMenu->AppendSeparator();
612 fileMenu->Append(ID_VIEW_HTML, wxT("&View as HTML"), wxT("View HTML"));
613 fileMenu->AppendSeparator();
614 fileMenu->Append(ID_Quit, wxT("E&xit\tAlt+X"), wxT("Quit this program"));
615
616 wxMenu* editMenu = new wxMenu;
617 editMenu->Append(wxID_UNDO, _("&Undo\tCtrl+Z"));
618 editMenu->Append(wxID_REDO, _("&Redo\tCtrl+Y"));
619 editMenu->AppendSeparator();
620 editMenu->Append(wxID_CUT, _("Cu&t\tCtrl+X"));
621 editMenu->Append(wxID_COPY, _("&Copy\tCtrl+C"));
622 editMenu->Append(wxID_PASTE, _("&Paste\tCtrl+V"));
623
624 editMenu->AppendSeparator();
625 editMenu->Append(wxID_SELECTALL, _("Select A&ll\tCtrl+A"));
626 #if 0
627 editMenu->AppendSeparator();
628 editMenu->Append(wxID_FIND, _("&Find...\tCtrl+F"));
629 editMenu->Append(stID_FIND_REPLACE, _("&Replace...\tCtrl+R"));
630 #endif
631
632 wxMenu* formatMenu = new wxMenu;
633 formatMenu->AppendCheckItem(ID_FORMAT_BOLD, _("&Bold\tCtrl+B"));
634 formatMenu->AppendCheckItem(ID_FORMAT_ITALIC, _("&Italic\tCtrl+I"));
635 formatMenu->AppendCheckItem(ID_FORMAT_UNDERLINE, _("&Underline\tCtrl+U"));
636 formatMenu->AppendSeparator();
637 formatMenu->AppendCheckItem(ID_FORMAT_STRIKETHROUGH, _("Stri&kethrough"));
638 formatMenu->AppendCheckItem(ID_FORMAT_SUPERSCRIPT, _("Superscrip&t"));
639 formatMenu->AppendCheckItem(ID_FORMAT_SUBSCRIPT, _("Subscrip&t"));
640 formatMenu->AppendSeparator();
641 formatMenu->AppendCheckItem(ID_FORMAT_ALIGN_LEFT, _("L&eft Align"));
642 formatMenu->AppendCheckItem(ID_FORMAT_ALIGN_RIGHT, _("&Right Align"));
643 formatMenu->AppendCheckItem(ID_FORMAT_ALIGN_CENTRE, _("&Centre"));
644 formatMenu->AppendSeparator();
645 formatMenu->Append(ID_FORMAT_INDENT_MORE, _("Indent &More"));
646 formatMenu->Append(ID_FORMAT_INDENT_LESS, _("Indent &Less"));
647 formatMenu->AppendSeparator();
648 formatMenu->Append(ID_FORMAT_PARAGRAPH_SPACING_MORE, _("Increase Paragraph &Spacing"));
649 formatMenu->Append(ID_FORMAT_PARAGRAPH_SPACING_LESS, _("Decrease &Paragraph Spacing"));
650 formatMenu->AppendSeparator();
651 formatMenu->Append(ID_FORMAT_LINE_SPACING_SINGLE, _("Normal Line Spacing"));
652 formatMenu->Append(ID_FORMAT_LINE_SPACING_HALF, _("1.5 Line Spacing"));
653 formatMenu->Append(ID_FORMAT_LINE_SPACING_DOUBLE, _("Double Line Spacing"));
654 formatMenu->AppendSeparator();
655 formatMenu->Append(ID_FORMAT_FONT, _("&Font..."));
656 formatMenu->Append(ID_FORMAT_IMAGE, _("Image Property"));
657 formatMenu->Append(ID_FORMAT_PARAGRAPH, _("&Paragraph..."));
658 formatMenu->Append(ID_FORMAT_CONTENT, _("Font and Pa&ragraph...\tShift+Ctrl+F"));
659 formatMenu->AppendSeparator();
660 formatMenu->Append(ID_SWITCH_STYLE_SHEETS, _("&Switch Style Sheets"));
661 formatMenu->Append(ID_MANAGE_STYLES, _("&Manage Styles"));
662
663 wxMenu* listsMenu = new wxMenu;
664 listsMenu->Append(ID_FORMAT_BULLETS_AND_NUMBERING, _("Bullets and &Numbering..."));
665 listsMenu->AppendSeparator();
666 listsMenu->Append(ID_FORMAT_NUMBER_LIST, _("Number List"));
667 listsMenu->Append(ID_FORMAT_ITEMIZE_LIST, _("Itemize List"));
668 listsMenu->Append(ID_FORMAT_RENUMBER_LIST, _("Renumber List"));
669 listsMenu->Append(ID_FORMAT_PROMOTE_LIST, _("Promote List Items"));
670 listsMenu->Append(ID_FORMAT_DEMOTE_LIST, _("Demote List Items"));
671 listsMenu->Append(ID_FORMAT_CLEAR_LIST, _("Clear List Formatting"));
672
673 wxMenu* insertMenu = new wxMenu;
674 insertMenu->Append(ID_INSERT_SYMBOL, _("&Symbol...\tCtrl+I"));
675 insertMenu->Append(ID_INSERT_URL, _("&URL..."));
676 insertMenu->Append(ID_INSERT_IMAGE, _("&Image..."));
677
678 // now append the freshly created menu to the menu bar...
679 wxMenuBar *menuBar = new wxMenuBar();
680 menuBar->Append(fileMenu, wxT("&File"));
681 menuBar->Append(editMenu, wxT("&Edit"));
682 menuBar->Append(formatMenu, wxT("F&ormat"));
683 menuBar->Append(listsMenu, wxT("&Lists"));
684 menuBar->Append(insertMenu, wxT("&Insert"));
685 menuBar->Append(helpMenu, wxT("&Help"));
686
687 // ... and attach this menu bar to the frame
688 SetMenuBar(menuBar);
689
690 // create a status bar just for fun (by default with 1 pane only)
691 // but don't create it on limited screen space (WinCE)
692 bool is_pda = wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA;
693
694 #if wxUSE_STATUSBAR
695 if ( !is_pda )
696 {
697 CreateStatusBar(2);
698 SetStatusText(wxT("Welcome to wxRichTextCtrl!"));
699 }
700 #endif
701
702 wxToolBar* toolBar = CreateToolBar();
703
704 toolBar->AddTool(wxID_OPEN, wxEmptyString, wxBitmap(open_xpm), _("Open"));
705 toolBar->AddTool(wxID_SAVEAS, wxEmptyString, wxBitmap(save_xpm), _("Save"));
706 toolBar->AddSeparator();
707 toolBar->AddTool(wxID_CUT, wxEmptyString, wxBitmap(cut_xpm), _("Cut"));
708 toolBar->AddTool(wxID_COPY, wxEmptyString, wxBitmap(copy_xpm), _("Copy"));
709 toolBar->AddTool(wxID_PASTE, wxEmptyString, wxBitmap(paste_xpm), _("Paste"));
710 toolBar->AddSeparator();
711 toolBar->AddTool(wxID_UNDO, wxEmptyString, wxBitmap(undo_xpm), _("Undo"));
712 toolBar->AddTool(wxID_REDO, wxEmptyString, wxBitmap(redo_xpm), _("Redo"));
713 toolBar->AddSeparator();
714 toolBar->AddCheckTool(ID_FORMAT_BOLD, wxEmptyString, wxBitmap(bold_xpm), wxNullBitmap, _("Bold"));
715 toolBar->AddCheckTool(ID_FORMAT_ITALIC, wxEmptyString, wxBitmap(italic_xpm), wxNullBitmap, _("Italic"));
716 toolBar->AddCheckTool(ID_FORMAT_UNDERLINE, wxEmptyString, wxBitmap(underline_xpm), wxNullBitmap, _("Underline"));
717 toolBar->AddSeparator();
718 toolBar->AddCheckTool(ID_FORMAT_ALIGN_LEFT, wxEmptyString, wxBitmap(alignleft_xpm), wxNullBitmap, _("Align Left"));
719 toolBar->AddCheckTool(ID_FORMAT_ALIGN_CENTRE, wxEmptyString, wxBitmap(centre_xpm), wxNullBitmap, _("Centre"));
720 toolBar->AddCheckTool(ID_FORMAT_ALIGN_RIGHT, wxEmptyString, wxBitmap(alignright_xpm), wxNullBitmap, _("Align Right"));
721 toolBar->AddSeparator();
722 toolBar->AddTool(ID_FORMAT_INDENT_LESS, wxEmptyString, wxBitmap(indentless_xpm), _("Indent Less"));
723 toolBar->AddTool(ID_FORMAT_INDENT_MORE, wxEmptyString, wxBitmap(indentmore_xpm), _("Indent More"));
724 toolBar->AddSeparator();
725 toolBar->AddTool(ID_FORMAT_FONT, wxEmptyString, wxBitmap(font_xpm), _("Font"));
726 toolBar->AddTool(ID_FORMAT_IMAGE, wxString("Im"), wxBitmap(font_xpm), _("Image Property"));
727
728 wxRichTextStyleComboCtrl* combo = new wxRichTextStyleComboCtrl(toolBar, ID_RICHTEXT_STYLE_COMBO, wxDefaultPosition, wxSize(200, -1));
729 toolBar->AddControl(combo);
730
731 toolBar->Realize();
732
733 wxSplitterWindow* splitter = new wxSplitterWindow(this, wxID_ANY, wxDefaultPosition, GetClientSize(), wxSP_LIVE_UPDATE);
734
735 wxFont textFont = wxFont(12, wxROMAN, wxNORMAL, wxNORMAL);
736 wxFont boldFont = wxFont(12, wxROMAN, wxNORMAL, wxBOLD);
737 wxFont italicFont = wxFont(12, wxROMAN, wxITALIC, wxNORMAL);
738
739 m_richTextCtrl = new wxRichTextCtrl(splitter, ID_RICHTEXT_CTRL, wxEmptyString, wxDefaultPosition, wxSize(200, 200), wxVSCROLL|wxHSCROLL|wxWANTS_CHARS);
740 wxFont font(12, wxROMAN, wxNORMAL, wxNORMAL);
741
742 m_richTextCtrl->SetFont(font);
743
744 m_richTextCtrl->SetMargins(10, 10);
745
746 m_richTextCtrl->SetStyleSheet(wxGetApp().GetStyleSheet());
747
748 combo->SetStyleSheet(wxGetApp().GetStyleSheet());
749 combo->SetRichTextCtrl(m_richTextCtrl);
750 combo->UpdateStyles();
751
752 wxRichTextStyleListCtrl* styleListCtrl = new wxRichTextStyleListCtrl(splitter, ID_RICHTEXT_STYLE_LIST);
753
754 wxSize display = wxGetDisplaySize();
755 if ( is_pda && ( display.GetWidth() < display.GetHeight() ) )
756 {
757 splitter->SplitHorizontally(m_richTextCtrl, styleListCtrl);
758 }
759 else
760 {
761 splitter->SplitVertically(m_richTextCtrl, styleListCtrl, 500);
762 }
763
764 splitter->UpdateSize();
765
766 styleListCtrl->SetStyleSheet(wxGetApp().GetStyleSheet());
767 styleListCtrl->SetRichTextCtrl(m_richTextCtrl);
768 styleListCtrl->UpdateStyles();
769
770 WriteInitialText();
771 }
772
773 // Write text
774 void MyFrame::WriteInitialText()
775 {
776 wxRichTextCtrl& r = *m_richTextCtrl;
777
778 r.SetDefaultStyle(wxRichTextAttr());
779
780 r.BeginSuppressUndo();
781
782 r.Freeze();
783
784 r.BeginParagraphSpacing(0, 20);
785
786 r.BeginAlignment(wxTEXT_ALIGNMENT_CENTRE);
787 r.BeginBold();
788
789 r.BeginFontSize(14);
790
791 wxString lineBreak = (wxChar) 29;
792
793 r.WriteText(wxString(wxT("Welcome to wxRichTextCtrl, a wxWidgets control")) + lineBreak + wxT("for editing and presenting styled text and images\n"));
794 r.EndFontSize();
795
796 r.BeginItalic();
797 r.WriteText(wxT("by Julian Smart"));
798 r.EndItalic();
799
800 r.EndBold();
801 r.Newline();
802
803 r.WriteImage(wxBitmap(zebra_xpm));
804
805 r.Newline();
806 r.Newline();
807
808 r.EndAlignment();
809
810 r.BeginAlignment(wxTEXT_ALIGNMENT_LEFT);
811 wxRichTextAttr imageAttr;
812 imageAttr.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_LEFT);
813 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.")));
814 r.WriteImage(wxBitmap(zebra_xpm), wxBITMAP_TYPE_PNG, imageAttr);
815
816 imageAttr.GetTextBoxAttr().GetTop().SetValue(200);
817 imageAttr.GetTextBoxAttr().GetTop().SetUnits(wxTEXT_ATTR_UNITS_PIXELS);
818 imageAttr.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_RIGHT);
819 r.WriteImage(wxBitmap(zebra_xpm), wxBITMAP_TYPE_PNG, imageAttr);
820 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.")));
821 r.EndAlignment();
822 r.Newline();
823
824 r.WriteText(wxT("What can you do with this thing? "));
825
826 r.WriteImage(wxBitmap(smiley_xpm));
827 r.WriteText(wxT(" Well, you can change text "));
828
829 r.BeginTextColour(wxColour(255, 0, 0));
830 r.WriteText(wxT("colour, like this red bit."));
831 r.EndTextColour();
832
833 wxRichTextAttr backgroundColourAttr;
834 backgroundColourAttr.SetBackgroundColour(*wxGREEN);
835 backgroundColourAttr.SetTextColour(wxColour(0, 0, 255));
836 r.BeginStyle(backgroundColourAttr);
837 r.WriteText(wxT(" And this blue on green bit."));
838 r.EndStyle();
839
840 r.WriteText(wxT(" Naturally you can make things "));
841 r.BeginBold();
842 r.WriteText(wxT("bold "));
843 r.EndBold();
844 r.BeginItalic();
845 r.WriteText(wxT("or italic "));
846 r.EndItalic();
847 r.BeginUnderline();
848 r.WriteText(wxT("or underlined."));
849 r.EndUnderline();
850
851 r.BeginFontSize(14);
852 r.WriteText(wxT(" Different font sizes on the same line is allowed, too."));
853 r.EndFontSize();
854
855 r.WriteText(wxT(" Next we'll show an indented paragraph."));
856
857 r.Newline();
858
859 r.BeginLeftIndent(60);
860 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."));
861 r.Newline();
862
863 r.EndLeftIndent();
864
865 r.WriteText(wxT("Next, we'll show a first-line indent, achieved using BeginLeftIndent(100, -40)."));
866
867 r.Newline();
868
869 r.BeginLeftIndent(100, -40);
870
871 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."));
872 r.Newline();
873
874 r.EndLeftIndent();
875
876 r.WriteText(wxT("Numbered bullets are possible, again using subindents:"));
877 r.Newline();
878
879 r.BeginNumberedBullet(1, 100, 60);
880 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."));
881 r.Newline();
882 r.EndNumberedBullet();
883
884 r.BeginNumberedBullet(2, 100, 60);
885 r.WriteText(wxT("This is my second item."));
886 r.Newline();
887 r.EndNumberedBullet();
888
889 r.WriteText(wxT("The following paragraph is right-indented:"));
890 r.Newline();
891
892 r.BeginRightIndent(200);
893
894 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."));
895 r.Newline();
896
897 r.EndRightIndent();
898
899 r.WriteText(wxT("The following paragraph is right-aligned with 1.5 line spacing:"));
900 r.Newline();
901
902 r.BeginAlignment(wxTEXT_ALIGNMENT_RIGHT);
903 r.BeginLineSpacing(wxTEXT_ATTR_LINE_SPACING_HALF);
904 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."));
905 r.Newline();
906 r.EndLineSpacing();
907 r.EndAlignment();
908
909 wxArrayInt tabs;
910 tabs.Add(400);
911 tabs.Add(600);
912 tabs.Add(800);
913 tabs.Add(1000);
914 wxRichTextAttr attr;
915 attr.SetFlags(wxTEXT_ATTR_TABS);
916 attr.SetTabs(tabs);
917 r.SetDefaultStyle(attr);
918
919 r.WriteText(wxT("This line contains tabs:\tFirst tab\tSecond tab\tThird tab"));
920 r.Newline();
921
922 r.WriteText(wxT("Other notable features of wxRichTextCtrl include:"));
923 r.Newline();
924
925 r.BeginSymbolBullet(wxT('*'), 100, 60);
926 r.WriteText(wxT("Compatibility with wxTextCtrl API"));
927 r.Newline();
928 r.EndSymbolBullet();
929
930 r.BeginSymbolBullet(wxT('*'), 100, 60);
931 r.WriteText(wxT("Easy stack-based BeginXXX()...EndXXX() style setting in addition to SetStyle()"));
932 r.Newline();
933 r.EndSymbolBullet();
934
935 r.BeginSymbolBullet(wxT('*'), 100, 60);
936 r.WriteText(wxT("XML loading and saving"));
937 r.Newline();
938 r.EndSymbolBullet();
939
940 r.BeginSymbolBullet(wxT('*'), 100, 60);
941 r.WriteText(wxT("Undo/Redo, with batching option and Undo suppressing"));
942 r.Newline();
943 r.EndSymbolBullet();
944
945 r.BeginSymbolBullet(wxT('*'), 100, 60);
946 r.WriteText(wxT("Clipboard copy and paste"));
947 r.Newline();
948 r.EndSymbolBullet();
949
950 r.BeginSymbolBullet(wxT('*'), 100, 60);
951 r.WriteText(wxT("wxRichTextStyleSheet with named character and paragraph styles, and control for applying named styles"));
952 r.Newline();
953 r.EndSymbolBullet();
954
955 r.BeginSymbolBullet(wxT('*'), 100, 60);
956 r.WriteText(wxT("A design that can easily be extended to other content types, ultimately with text boxes, tables, controls, and so on"));
957 r.Newline();
958 r.EndSymbolBullet();
959
960 // Make a style suitable for showing a URL
961 wxRichTextAttr urlStyle;
962 urlStyle.SetTextColour(*wxBLUE);
963 urlStyle.SetFontUnderlined(true);
964
965 r.WriteText(wxT("wxRichTextCtrl can also display URLs, such as this one: "));
966 r.BeginStyle(urlStyle);
967 r.BeginURL(wxT("http://www.wxwidgets.org"));
968 r.WriteText(wxT("The wxWidgets Web Site"));
969 r.EndURL();
970 r.EndStyle();
971 r.WriteText(wxT(". Click on the URL to generate an event."));
972
973 r.Newline();
974
975 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"));
976
977 r.EndParagraphSpacing();
978 #if 1
979
980 {
981 // Add a text box
982
983 r.Newline();
984
985 wxRichTextAttr attr;
986 attr.GetTextBoxAttr().GetMargins().GetLeft().SetValue(20, wxTEXT_ATTR_UNITS_PIXELS);
987 attr.GetTextBoxAttr().GetMargins().GetTop().SetValue(20, wxTEXT_ATTR_UNITS_PIXELS);
988 attr.GetTextBoxAttr().GetMargins().GetRight().SetValue(20, wxTEXT_ATTR_UNITS_PIXELS);
989 attr.GetTextBoxAttr().GetMargins().GetBottom().SetValue(20, wxTEXT_ATTR_UNITS_PIXELS);
990
991 attr.GetTextBoxAttr().GetBorder().SetColour(*wxBLACK);
992 attr.GetTextBoxAttr().GetBorder().SetWidth(1, wxTEXT_ATTR_UNITS_PIXELS);
993 attr.GetTextBoxAttr().GetBorder().SetStyle(wxTEXT_BOX_ATTR_BORDER_SOLID);
994
995 wxRichTextBox* textBox = r.WriteTextBox(attr);
996 r.SetFocusObject(textBox);
997
998 r.WriteText(wxT("This is a text box. Just testing! Once more unto the breach, dear friends, once more..."));
999
1000 r.SetFocusObject(NULL); // Set the focus back to the main buffer
1001 r.SetInsertionPointEnd();
1002 }
1003 #endif
1004 #if 1
1005 {
1006 // Add a table
1007
1008 r.Newline();
1009
1010 wxRichTextAttr attr;
1011 attr.GetTextBoxAttr().GetMargins().GetLeft().SetValue(5, wxTEXT_ATTR_UNITS_PIXELS);
1012 attr.GetTextBoxAttr().GetMargins().GetTop().SetValue(5, wxTEXT_ATTR_UNITS_PIXELS);
1013 attr.GetTextBoxAttr().GetMargins().GetRight().SetValue(5, wxTEXT_ATTR_UNITS_PIXELS);
1014 attr.GetTextBoxAttr().GetMargins().GetBottom().SetValue(5, wxTEXT_ATTR_UNITS_PIXELS);
1015 attr.GetTextBoxAttr().GetPadding() = attr.GetTextBoxAttr().GetMargins();
1016
1017 attr.GetTextBoxAttr().GetBorder().SetColour(*wxBLACK);
1018 attr.GetTextBoxAttr().GetBorder().SetWidth(1, wxTEXT_ATTR_UNITS_PIXELS);
1019 attr.GetTextBoxAttr().GetBorder().SetStyle(wxTEXT_BOX_ATTR_BORDER_SOLID);
1020
1021 wxRichTextAttr cellAttr = attr;
1022 cellAttr.GetTextBoxAttr().GetWidth().SetValue(200, wxTEXT_ATTR_UNITS_PIXELS);
1023 cellAttr.GetTextBoxAttr().GetHeight().SetValue(150, wxTEXT_ATTR_UNITS_PIXELS);
1024
1025 wxRichTextTable* table = r.WriteTable(3, 2, attr, cellAttr);
1026 int i, j;
1027 for (j = 0; j < table->GetRowCount(); j++)
1028 {
1029 for (i = 0; i < table->GetColumnCount(); i++)
1030 {
1031 wxString msg = wxString::Format(wxT("This is cell %d, %d"), (j+1), (i+1));
1032 r.SetFocusObject(table->GetCell(j, i));
1033 r.WriteText(msg);
1034 }
1035 }
1036 r.SetFocusObject(NULL); // Set the focus back to the main buffer
1037 r.SetInsertionPointEnd();
1038 }
1039 #endif
1040
1041 r.Thaw();
1042
1043 r.EndSuppressUndo();
1044 }
1045
1046 // event handlers
1047
1048 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
1049 {
1050 // true is to force the frame to close
1051 Close(true);
1052 }
1053
1054 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
1055 {
1056 wxString msg;
1057 msg.Printf( wxT("This is a demo for wxRichTextCtrl, a control for editing styled text.\n(c) Julian Smart, 2005"));
1058 wxMessageBox(msg, wxT("About wxRichTextCtrl Sample"), wxOK | wxICON_INFORMATION, this);
1059 }
1060
1061 // Forward command events to the current rich text control, if any
1062 bool MyFrame::ProcessEvent(wxEvent& event)
1063 {
1064 if (event.IsCommandEvent() && !event.IsKindOf(CLASSINFO(wxChildFocusEvent)))
1065 {
1066 // Problem: we can get infinite recursion because the events
1067 // climb back up to this frame, and repeat.
1068 // Assume that command events don't cause another command event
1069 // to be called, so we can rely on inCommand not being overwritten
1070
1071 static int s_eventType = 0;
1072 static wxWindowID s_id = 0;
1073
1074 if (s_id != event.GetId() && s_eventType != event.GetEventType())
1075 {
1076 s_eventType = event.GetEventType();
1077 s_id = event.GetId();
1078
1079 wxWindow* focusWin = wxFindFocusDescendant(this);
1080 if (focusWin && focusWin->GetEventHandler()->ProcessEvent(event))
1081 {
1082 //s_command = NULL;
1083 s_eventType = 0;
1084 s_id = 0;
1085 return true;
1086 }
1087
1088 s_eventType = 0;
1089 s_id = 0;
1090 }
1091 else
1092 {
1093 return false;
1094 }
1095 }
1096
1097 return wxFrame::ProcessEvent(event);
1098 }
1099
1100 void MyFrame::OnOpen(wxCommandEvent& WXUNUSED(event))
1101 {
1102 wxString path;
1103 wxString filename;
1104 wxArrayInt fileTypes;
1105
1106 wxString filter = wxRichTextBuffer::GetExtWildcard(false, false, & fileTypes);
1107 if (!filter.empty())
1108 filter += wxT("|");
1109 filter += wxT("All files (*.*)|*.*");
1110
1111 wxFileDialog dialog(this,
1112 _("Choose a filename"),
1113 path,
1114 filename,
1115 filter,
1116 wxFD_OPEN);
1117
1118 if (dialog.ShowModal() == wxID_OK)
1119 {
1120 wxString path = dialog.GetPath();
1121
1122 if (!path.empty())
1123 {
1124 int filterIndex = dialog.GetFilterIndex();
1125 int fileType = (filterIndex < (int) fileTypes.GetCount())
1126 ? fileTypes[filterIndex]
1127 : wxRICHTEXT_TYPE_TEXT;
1128 m_richTextCtrl->LoadFile(path, fileType);
1129 }
1130 }
1131 }
1132
1133 void MyFrame::OnSave(wxCommandEvent& event)
1134 {
1135 if (m_richTextCtrl->GetFilename().empty())
1136 {
1137 OnSaveAs(event);
1138 return;
1139 }
1140 m_richTextCtrl->SaveFile();
1141 }
1142
1143 void MyFrame::OnSaveAs(wxCommandEvent& WXUNUSED(event))
1144 {
1145 wxString filter = wxRichTextBuffer::GetExtWildcard(false, true);
1146 wxString path;
1147 wxString filename;
1148
1149 wxFileDialog dialog(this,
1150 _("Choose a filename"),
1151 path,
1152 filename,
1153 filter,
1154 wxFD_SAVE);
1155
1156 if (dialog.ShowModal() == wxID_OK)
1157 {
1158 wxString path = dialog.GetPath();
1159
1160 if (!path.empty())
1161 {
1162 wxBusyCursor busy;
1163 wxStopWatch stopwatch;
1164
1165 m_richTextCtrl->SaveFile(path);
1166
1167 long t = stopwatch.Time();
1168 wxLogDebug(wxT("Saving took %ldms"), t);
1169 wxMessageBox(wxString::Format(wxT("Saving took %ldms"), t));
1170 }
1171 }
1172 }
1173
1174 void MyFrame::OnBold(wxCommandEvent& WXUNUSED(event))
1175 {
1176 m_richTextCtrl->ApplyBoldToSelection();
1177 }
1178
1179 void MyFrame::OnItalic(wxCommandEvent& WXUNUSED(event))
1180 {
1181 m_richTextCtrl->ApplyItalicToSelection();
1182 }
1183
1184 void MyFrame::OnUnderline(wxCommandEvent& WXUNUSED(event))
1185 {
1186 m_richTextCtrl->ApplyUnderlineToSelection();
1187 }
1188
1189 void MyFrame::OnStrikethrough(wxCommandEvent& WXUNUSED(event))
1190 {
1191 m_richTextCtrl->ApplyTextEffectToSelection(wxTEXT_ATTR_EFFECT_STRIKETHROUGH);
1192 }
1193
1194 void MyFrame::OnSuperscript(wxCommandEvent& WXUNUSED(event))
1195 {
1196 m_richTextCtrl->ApplyTextEffectToSelection(wxTEXT_ATTR_EFFECT_SUPERSCRIPT);
1197 }
1198
1199 void MyFrame::OnSubscript(wxCommandEvent& WXUNUSED(event))
1200 {
1201 m_richTextCtrl->ApplyTextEffectToSelection(wxTEXT_ATTR_EFFECT_SUBSCRIPT);
1202 }
1203
1204
1205 void MyFrame::OnUpdateBold(wxUpdateUIEvent& event)
1206 {
1207 event.Check(m_richTextCtrl->IsSelectionBold());
1208 }
1209
1210 void MyFrame::OnUpdateItalic(wxUpdateUIEvent& event)
1211 {
1212 event.Check(m_richTextCtrl->IsSelectionItalics());
1213 }
1214
1215 void MyFrame::OnUpdateUnderline(wxUpdateUIEvent& event)
1216 {
1217 event.Check(m_richTextCtrl->IsSelectionUnderlined());
1218 }
1219
1220 void MyFrame::OnUpdateStrikethrough(wxUpdateUIEvent& event)
1221 {
1222 event.Check(m_richTextCtrl->DoesSelectionHaveTextEffectFlag(wxTEXT_ATTR_EFFECT_STRIKETHROUGH));
1223 }
1224
1225 void MyFrame::OnUpdateSuperscript(wxUpdateUIEvent& event)
1226 {
1227 event.Check(m_richTextCtrl->DoesSelectionHaveTextEffectFlag(wxTEXT_ATTR_EFFECT_SUPERSCRIPT));
1228 }
1229
1230 void MyFrame::OnUpdateSubscript(wxUpdateUIEvent& event)
1231 {
1232 event.Check(m_richTextCtrl->DoesSelectionHaveTextEffectFlag(wxTEXT_ATTR_EFFECT_SUBSCRIPT));
1233 }
1234
1235 void MyFrame::OnAlignLeft(wxCommandEvent& WXUNUSED(event))
1236 {
1237 m_richTextCtrl->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_LEFT);
1238 }
1239
1240 void MyFrame::OnAlignCentre(wxCommandEvent& WXUNUSED(event))
1241 {
1242 m_richTextCtrl->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_CENTRE);
1243 }
1244
1245 void MyFrame::OnAlignRight(wxCommandEvent& WXUNUSED(event))
1246 {
1247 m_richTextCtrl->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_RIGHT);
1248 }
1249
1250 void MyFrame::OnUpdateAlignLeft(wxUpdateUIEvent& event)
1251 {
1252 event.Check(m_richTextCtrl->IsSelectionAligned(wxTEXT_ALIGNMENT_LEFT));
1253 }
1254
1255 void MyFrame::OnUpdateAlignCentre(wxUpdateUIEvent& event)
1256 {
1257 event.Check(m_richTextCtrl->IsSelectionAligned(wxTEXT_ALIGNMENT_CENTRE));
1258 }
1259
1260 void MyFrame::OnUpdateAlignRight(wxUpdateUIEvent& event)
1261 {
1262 event.Check(m_richTextCtrl->IsSelectionAligned(wxTEXT_ALIGNMENT_RIGHT));
1263 }
1264
1265 void MyFrame::OnFont(wxCommandEvent& WXUNUSED(event))
1266 {
1267 wxRichTextRange range;
1268 if (m_richTextCtrl->HasSelection())
1269 range = m_richTextCtrl->GetSelectionRange();
1270 else
1271 range = wxRichTextRange(0, m_richTextCtrl->GetLastPosition()+1);
1272
1273 int pages = wxRICHTEXT_FORMAT_FONT;
1274
1275 wxRichTextFormattingDialog formatDlg(pages, this);
1276 formatDlg.GetStyle(m_richTextCtrl, range);
1277
1278 if (formatDlg.ShowModal() == wxID_OK)
1279 {
1280 formatDlg.ApplyStyle(m_richTextCtrl, range, wxRICHTEXT_SETSTYLE_WITH_UNDO|wxRICHTEXT_SETSTYLE_OPTIMIZE|wxRICHTEXT_SETSTYLE_CHARACTERS_ONLY);
1281 }
1282
1283 // Old method using wxFontDialog
1284 #if 0
1285 if (!m_richTextCtrl->HasSelection())
1286 return;
1287
1288 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1289 wxFontData fontData;
1290
1291 wxRichTextAttr attr;
1292 attr.SetFlags(wxTEXT_ATTR_FONT);
1293
1294 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1295 fontData.SetInitialFont(attr.GetFont());
1296
1297 wxFontDialog dialog(this, fontData);
1298 if (dialog.ShowModal() == wxID_OK)
1299 {
1300 fontData = dialog.GetFontData();
1301 attr.SetFlags(wxTEXT_ATTR_FONT);
1302 attr.SetFont(fontData.GetChosenFont());
1303 if (attr.GetFont().IsOk())
1304 {
1305 m_richTextCtrl->SetStyle(range, attr);
1306 }
1307 }
1308 #endif
1309 }
1310
1311 void MyFrame::OnImage(wxCommandEvent& WXUNUSED(event))
1312 {
1313 wxRichTextRange range;
1314 wxASSERT(m_richTextCtrl->HasSelection());
1315
1316 range = m_richTextCtrl->GetSelectionRange();
1317 wxASSERT(range.ToInternal().GetLength() == 1);
1318
1319 wxRichTextImage* image = wxDynamicCast(m_richTextCtrl->GetFocusObject()->GetLeafObjectAtPosition(range.GetStart()), wxRichTextImage);
1320 if (image)
1321 {
1322 wxRichTextObjectPropertiesDialog imageDlg(image, this);
1323
1324 if (imageDlg.ShowModal() == wxID_OK)
1325 {
1326 imageDlg.ApplyStyle(m_richTextCtrl);
1327 }
1328 }
1329 }
1330
1331 void MyFrame::OnParagraph(wxCommandEvent& WXUNUSED(event))
1332 {
1333 wxRichTextRange range;
1334 if (m_richTextCtrl->HasSelection())
1335 range = m_richTextCtrl->GetSelectionRange();
1336 else
1337 range = wxRichTextRange(0, m_richTextCtrl->GetLastPosition()+1);
1338
1339 int pages = wxRICHTEXT_FORMAT_INDENTS_SPACING|wxRICHTEXT_FORMAT_TABS|wxRICHTEXT_FORMAT_BULLETS;
1340
1341 wxRichTextFormattingDialog formatDlg(pages, this);
1342 formatDlg.GetStyle(m_richTextCtrl, range);
1343
1344 if (formatDlg.ShowModal() == wxID_OK)
1345 {
1346 formatDlg.ApplyStyle(m_richTextCtrl, range);
1347 }
1348 }
1349
1350 void MyFrame::OnFormat(wxCommandEvent& WXUNUSED(event))
1351 {
1352 wxRichTextRange range;
1353 if (m_richTextCtrl->HasSelection())
1354 range = m_richTextCtrl->GetSelectionRange();
1355 else
1356 range = wxRichTextRange(0, m_richTextCtrl->GetLastPosition()+1);
1357
1358 int pages = wxRICHTEXT_FORMAT_FONT|wxRICHTEXT_FORMAT_INDENTS_SPACING|wxRICHTEXT_FORMAT_TABS|wxRICHTEXT_FORMAT_BULLETS;
1359
1360 wxRichTextFormattingDialog formatDlg(pages, this);
1361 formatDlg.GetStyle(m_richTextCtrl, range);
1362
1363 if (formatDlg.ShowModal() == wxID_OK)
1364 {
1365 formatDlg.ApplyStyle(m_richTextCtrl, range);
1366 }
1367 }
1368
1369 void MyFrame::OnUpdateFormat(wxUpdateUIEvent& event)
1370 {
1371 event.Enable(m_richTextCtrl->HasSelection());
1372 }
1373
1374 void MyFrame::OnUpdateImage(wxUpdateUIEvent& event)
1375 {
1376 wxRichTextRange range;
1377 wxRichTextObject *obj;
1378
1379 range = m_richTextCtrl->GetSelectionRange();
1380 if (range.ToInternal().GetLength() == 1)
1381 {
1382 obj = m_richTextCtrl->GetFocusObject()->GetLeafObjectAtPosition(range.GetStart());
1383 if (obj && obj->IsKindOf(CLASSINFO(wxRichTextImage)))
1384 {
1385 event.Enable(true);
1386 return;
1387 }
1388 }
1389
1390 event.Enable(false);
1391 }
1392
1393 void MyFrame::OnIndentMore(wxCommandEvent& WXUNUSED(event))
1394 {
1395 wxRichTextAttr attr;
1396 attr.SetFlags(wxTEXT_ATTR_LEFT_INDENT);
1397
1398 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1399 {
1400 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1401 if (m_richTextCtrl->HasSelection())
1402 range = m_richTextCtrl->GetSelectionRange();
1403
1404 attr.SetLeftIndent(attr.GetLeftIndent() + 100);
1405
1406 attr.SetFlags(wxTEXT_ATTR_LEFT_INDENT);
1407 m_richTextCtrl->SetStyle(range, attr);
1408 }
1409 }
1410
1411 void MyFrame::OnIndentLess(wxCommandEvent& WXUNUSED(event))
1412 {
1413 wxRichTextAttr attr;
1414 attr.SetFlags(wxTEXT_ATTR_LEFT_INDENT);
1415
1416 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1417 {
1418 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1419 if (m_richTextCtrl->HasSelection())
1420 range = m_richTextCtrl->GetSelectionRange();
1421
1422 if (attr.GetLeftIndent() > 0)
1423 {
1424 attr.SetLeftIndent(wxMax(0, attr.GetLeftIndent() - 100));
1425
1426 m_richTextCtrl->SetStyle(range, attr);
1427 }
1428 }
1429 }
1430
1431 void MyFrame::OnLineSpacingHalf(wxCommandEvent& WXUNUSED(event))
1432 {
1433 wxRichTextAttr attr;
1434 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1435
1436 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1437 {
1438 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1439 if (m_richTextCtrl->HasSelection())
1440 range = m_richTextCtrl->GetSelectionRange();
1441
1442 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1443 attr.SetLineSpacing(15);
1444
1445 m_richTextCtrl->SetStyle(range, attr);
1446 }
1447 }
1448
1449 void MyFrame::OnLineSpacingDouble(wxCommandEvent& WXUNUSED(event))
1450 {
1451 wxRichTextAttr attr;
1452 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1453
1454 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1455 {
1456 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1457 if (m_richTextCtrl->HasSelection())
1458 range = m_richTextCtrl->GetSelectionRange();
1459
1460 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1461 attr.SetLineSpacing(20);
1462
1463 m_richTextCtrl->SetStyle(range, attr);
1464 }
1465 }
1466
1467 void MyFrame::OnLineSpacingSingle(wxCommandEvent& WXUNUSED(event))
1468 {
1469 wxRichTextAttr attr;
1470 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1471
1472 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1473 {
1474 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1475 if (m_richTextCtrl->HasSelection())
1476 range = m_richTextCtrl->GetSelectionRange();
1477
1478 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1479 attr.SetLineSpacing(0); // Can also use 10
1480
1481 m_richTextCtrl->SetStyle(range, attr);
1482 }
1483 }
1484
1485 void MyFrame::OnParagraphSpacingMore(wxCommandEvent& WXUNUSED(event))
1486 {
1487 wxRichTextAttr attr;
1488 attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER);
1489
1490 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1491 {
1492 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1493 if (m_richTextCtrl->HasSelection())
1494 range = m_richTextCtrl->GetSelectionRange();
1495
1496 attr.SetParagraphSpacingAfter(attr.GetParagraphSpacingAfter() + 20);
1497
1498 attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER);
1499 m_richTextCtrl->SetStyle(range, attr);
1500 }
1501 }
1502
1503 void MyFrame::OnParagraphSpacingLess(wxCommandEvent& WXUNUSED(event))
1504 {
1505 wxRichTextAttr attr;
1506 attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER);
1507
1508 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1509 {
1510 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1511 if (m_richTextCtrl->HasSelection())
1512 range = m_richTextCtrl->GetSelectionRange();
1513
1514 if (attr.GetParagraphSpacingAfter() >= 20)
1515 {
1516 attr.SetParagraphSpacingAfter(attr.GetParagraphSpacingAfter() - 20);
1517
1518 attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER);
1519 m_richTextCtrl->SetStyle(range, attr);
1520 }
1521 }
1522 }
1523
1524 void MyFrame::OnReload(wxCommandEvent& WXUNUSED(event))
1525 {
1526 m_richTextCtrl->Clear();
1527 WriteInitialText();
1528 }
1529
1530 void MyFrame::OnViewHTML(wxCommandEvent& WXUNUSED(event))
1531 {
1532 wxDialog dialog(this, wxID_ANY, _("HTML"), wxDefaultPosition, wxSize(500, 400), wxDEFAULT_DIALOG_STYLE);
1533
1534 wxBoxSizer* boxSizer = new wxBoxSizer(wxVERTICAL);
1535 dialog.SetSizer(boxSizer);
1536
1537 wxHtmlWindow* win = new wxHtmlWindow(& dialog, wxID_ANY, wxDefaultPosition, wxSize(500, 400), wxSUNKEN_BORDER);
1538 boxSizer->Add(win, 1, wxALL, 5);
1539
1540 wxButton* cancelButton = new wxButton(& dialog, wxID_CANCEL, wxT("&Close"));
1541 boxSizer->Add(cancelButton, 0, wxALL|wxCENTRE, 5);
1542
1543 wxString text;
1544 wxStringOutputStream strStream(& text);
1545
1546 wxRichTextHTMLHandler htmlHandler;
1547 htmlHandler.SetFlags(wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_MEMORY);
1548
1549 wxArrayInt fontSizeMapping;
1550 fontSizeMapping.Add(7);
1551 fontSizeMapping.Add(9);
1552 fontSizeMapping.Add(11);
1553 fontSizeMapping.Add(12);
1554 fontSizeMapping.Add(14);
1555 fontSizeMapping.Add(22);
1556 fontSizeMapping.Add(100);
1557
1558 htmlHandler.SetFontSizeMapping(fontSizeMapping);
1559
1560 if (htmlHandler.SaveFile(& m_richTextCtrl->GetBuffer(), strStream))
1561 {
1562 win->SetPage(text);
1563 }
1564
1565 boxSizer->Fit(& dialog);
1566
1567 dialog.ShowModal();
1568
1569 // Now delete the temporary in-memory images
1570 htmlHandler.DeleteTemporaryImages();
1571 }
1572
1573 // Demonstrates how you can change the style sheets and have the changes
1574 // reflected in the control content without wiping out character formatting.
1575
1576 void MyFrame::OnSwitchStyleSheets(wxCommandEvent& WXUNUSED(event))
1577 {
1578 static wxRichTextStyleSheet* gs_AlternateStyleSheet = NULL;
1579
1580 wxRichTextStyleListCtrl *styleList = (wxRichTextStyleListCtrl*) FindWindow(ID_RICHTEXT_STYLE_LIST);
1581 wxRichTextStyleComboCtrl* styleCombo = (wxRichTextStyleComboCtrl*) FindWindow(ID_RICHTEXT_STYLE_COMBO);
1582
1583 wxRichTextStyleSheet* sheet = m_richTextCtrl->GetStyleSheet();
1584
1585 // One-time creation of an alternate style sheet
1586 if (!gs_AlternateStyleSheet)
1587 {
1588 gs_AlternateStyleSheet = new wxRichTextStyleSheet(*sheet);
1589
1590 // Make some modifications
1591 for (int i = 0; i < (int) gs_AlternateStyleSheet->GetParagraphStyleCount(); i++)
1592 {
1593 wxRichTextParagraphStyleDefinition* def = gs_AlternateStyleSheet->GetParagraphStyle(i);
1594
1595 if (def->GetStyle().HasTextColour())
1596 def->GetStyle().SetTextColour(*wxBLUE);
1597
1598 if (def->GetStyle().HasAlignment())
1599 {
1600 if (def->GetStyle().GetAlignment() == wxTEXT_ALIGNMENT_CENTRE)
1601 def->GetStyle().SetAlignment(wxTEXT_ALIGNMENT_RIGHT);
1602 else if (def->GetStyle().GetAlignment() == wxTEXT_ALIGNMENT_LEFT)
1603 def->GetStyle().SetAlignment(wxTEXT_ALIGNMENT_CENTRE);
1604 }
1605 if (def->GetStyle().HasLeftIndent())
1606 {
1607 def->GetStyle().SetLeftIndent(def->GetStyle().GetLeftIndent() * 2);
1608 }
1609 }
1610 }
1611
1612 // Switch sheets
1613 wxRichTextStyleSheet* tmp = gs_AlternateStyleSheet;
1614 gs_AlternateStyleSheet = sheet;
1615 sheet = tmp;
1616
1617 m_richTextCtrl->SetStyleSheet(sheet);
1618 m_richTextCtrl->ApplyStyleSheet(sheet); // Makes the control reflect the new style definitions
1619
1620 styleList->SetStyleSheet(sheet);
1621 styleList->UpdateStyles();
1622
1623 styleCombo->SetStyleSheet(sheet);
1624 styleCombo->UpdateStyles();
1625 }
1626
1627 void MyFrame::OnManageStyles(wxCommandEvent& WXUNUSED(event))
1628 {
1629 wxRichTextStyleSheet* sheet = m_richTextCtrl->GetStyleSheet();
1630
1631 int flags = wxRICHTEXT_ORGANISER_CREATE_STYLES|wxRICHTEXT_ORGANISER_EDIT_STYLES;
1632
1633 wxRichTextStyleOrganiserDialog dlg(flags, sheet, NULL, this, wxID_ANY, _("Style Manager"));
1634 dlg.ShowModal();
1635 }
1636
1637 void MyFrame::OnInsertSymbol(wxCommandEvent& WXUNUSED(event))
1638 {
1639 wxRichTextAttr attr;
1640 attr.SetFlags(wxTEXT_ATTR_FONT);
1641 m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr);
1642
1643 wxString currentFontName;
1644 if (attr.HasFont() && attr.GetFont().IsOk())
1645 currentFontName = attr.GetFont().GetFaceName();
1646
1647 // Don't set the initial font in the dialog (so the user is choosing
1648 // 'normal text', i.e. the current font) but do tell the dialog
1649 // what 'normal text' is.
1650
1651 wxSymbolPickerDialog dlg(wxT("*"), wxEmptyString, currentFontName, this);
1652
1653 if (dlg.ShowModal() == wxID_OK)
1654 {
1655 if (dlg.HasSelection())
1656 {
1657 long insertionPoint = m_richTextCtrl->GetInsertionPoint();
1658
1659 m_richTextCtrl->WriteText(dlg.GetSymbol());
1660
1661 if (!dlg.UseNormalFont())
1662 {
1663 wxFont font(attr.GetFont());
1664 font.SetFaceName(dlg.GetFontName());
1665 attr.SetFont(font);
1666 m_richTextCtrl->SetStyle(insertionPoint, insertionPoint+1, attr);
1667 }
1668 }
1669 }
1670 }
1671
1672 void MyFrame::OnNumberList(wxCommandEvent& WXUNUSED(event))
1673 {
1674 if (m_richTextCtrl->HasSelection())
1675 {
1676 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1677 m_richTextCtrl->SetListStyle(range, wxT("Numbered List 1"), wxRICHTEXT_SETSTYLE_WITH_UNDO|wxRICHTEXT_SETSTYLE_RENUMBER);
1678 }
1679 }
1680
1681 void MyFrame::OnBulletsAndNumbering(wxCommandEvent& WXUNUSED(event))
1682 {
1683 wxRichTextStyleSheet* sheet = m_richTextCtrl->GetStyleSheet();
1684
1685 int flags = wxRICHTEXT_ORGANISER_BROWSE_NUMBERING;
1686
1687 wxRichTextStyleOrganiserDialog dlg(flags, sheet, m_richTextCtrl, this, wxID_ANY, _("Bullets and Numbering"));
1688 if (dlg.ShowModal() == wxID_OK)
1689 {
1690 if (dlg.GetSelectedStyleDefinition())
1691 dlg.ApplyStyle();
1692 }
1693 }
1694
1695 void MyFrame::OnItemizeList(wxCommandEvent& WXUNUSED(event))
1696 {
1697 if (m_richTextCtrl->HasSelection())
1698 {
1699 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1700 m_richTextCtrl->SetListStyle(range, wxT("Bullet List 1"));
1701 }
1702 }
1703
1704 void MyFrame::OnRenumberList(wxCommandEvent& WXUNUSED(event))
1705 {
1706 if (m_richTextCtrl->HasSelection())
1707 {
1708 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1709 m_richTextCtrl->NumberList(range, NULL, wxRICHTEXT_SETSTYLE_WITH_UNDO|wxRICHTEXT_SETSTYLE_RENUMBER);
1710 }
1711 }
1712
1713 void MyFrame::OnPromoteList(wxCommandEvent& WXUNUSED(event))
1714 {
1715 if (m_richTextCtrl->HasSelection())
1716 {
1717 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1718 m_richTextCtrl->PromoteList(1, range, NULL);
1719 }
1720 }
1721
1722 void MyFrame::OnDemoteList(wxCommandEvent& WXUNUSED(event))
1723 {
1724 if (m_richTextCtrl->HasSelection())
1725 {
1726 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1727 m_richTextCtrl->PromoteList(-1, range, NULL);
1728 }
1729 }
1730
1731 void MyFrame::OnClearList(wxCommandEvent& WXUNUSED(event))
1732 {
1733 if (m_richTextCtrl->HasSelection())
1734 {
1735 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1736 m_richTextCtrl->ClearListStyle(range);
1737 }
1738 }
1739
1740 void MyFrame::OnInsertURL(wxCommandEvent& WXUNUSED(event))
1741 {
1742 wxString url = wxGetTextFromUser(_("URL:"), _("Insert URL"));
1743 if (!url.IsEmpty())
1744 {
1745 // Make a style suitable for showing a URL
1746 wxRichTextAttr urlStyle;
1747 urlStyle.SetTextColour(*wxBLUE);
1748 urlStyle.SetFontUnderlined(true);
1749
1750 m_richTextCtrl->BeginStyle(urlStyle);
1751 m_richTextCtrl->BeginURL(url);
1752 m_richTextCtrl->WriteText(url);
1753 m_richTextCtrl->EndURL();
1754 m_richTextCtrl->EndStyle();
1755 }
1756 }
1757
1758 void MyFrame::OnInsertImage(wxCommandEvent& WXUNUSED(event))
1759 {
1760 wxFileDialog dialog(this, _("Choose an image"), "", "", "BMP and GIF files (*.bmp;*.gif)|*.bmp;*.gif|PNG files (*.png)|*.png");
1761 if (dialog.ShowModal() == wxID_OK)
1762 {
1763 wxString path = dialog.GetPath();
1764 m_richTextCtrl->WriteImage(path, wxBITMAP_TYPE_ANY);
1765 }
1766 }
1767
1768 void MyFrame::OnURL(wxTextUrlEvent& event)
1769 {
1770 wxMessageBox(event.GetString());
1771 }
1772
1773 // Veto style sheet replace events when loading from XML, since we want
1774 // to keep the original style sheet.
1775 void MyFrame::OnStyleSheetReplacing(wxRichTextEvent& event)
1776 {
1777 event.Veto();
1778 }
1779
1780 void MyFrame::OnPrint(wxCommandEvent& WXUNUSED(event))
1781 {
1782 wxGetApp().GetPrinting()->PrintBuffer(m_richTextCtrl->GetBuffer());
1783 }
1784
1785 void MyFrame::OnPreview(wxCommandEvent& WXUNUSED(event))
1786 {
1787 wxGetApp().GetPrinting()->PreviewBuffer(m_richTextCtrl->GetBuffer());
1788 }
1789
1790 void MyFrame::OnPageSetup(wxCommandEvent& WXUNUSED(event))
1791 {
1792 wxDialog dialog(this, wxID_ANY, wxT("Testing"), wxPoint(10, 10), wxSize(400, 300), wxDEFAULT_DIALOG_STYLE);
1793
1794 wxNotebook* nb = new wxNotebook(& dialog, wxID_ANY, wxPoint(5, 5), wxSize(300, 250));
1795 wxPanel* panel = new wxPanel(nb, wxID_ANY, wxDefaultPosition, wxDefaultSize);
1796 wxPanel* panel2 = new wxPanel(nb, wxID_ANY, wxDefaultPosition, wxDefaultSize);
1797
1798 new wxRichTextCtrl(panel, wxID_ANY, wxEmptyString, wxPoint(5, 5), wxSize(200, 150), wxVSCROLL|wxTE_READONLY);
1799 nb->AddPage(panel, wxT("Page 1"));
1800
1801 new wxRichTextCtrl(panel2, wxID_ANY, wxEmptyString, wxPoint(5, 5), wxSize(200, 150), wxVSCROLL|wxTE_READONLY);
1802 nb->AddPage(panel2, wxT("Page 2"));
1803
1804 new wxButton(& dialog, wxID_OK, wxT("OK"), wxPoint(5, 180));
1805
1806 dialog.ShowModal();
1807
1808 // wxGetApp().GetPrinting()->PageSetup();
1809 }