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