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