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