]> git.saurik.com Git - wxWidgets.git/blame - samples/richtext/richtext.cpp
Resolve ambiguity between GetClientXXX() methods in wxOSX wxComboBox.
[wxWidgets.git] / samples / richtext / richtext.cpp
CommitLineData
5d7836c4 1/////////////////////////////////////////////////////////////////////////////
dbf38e88 2// Name: samples/richtext/richtext.cpp
5d7836c4
JS
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"
bec80f4f 37#include "wx/stopwatch.h"
5d7836c4 38
720cc10a
JS
39#if wxUSE_FILESYSTEM
40#include "wx/filesys.h"
41#include "wx/fs_mem.h"
42#endif
43
2569ebc2
JS
44#if wxUSE_HELP
45#include "wx/cshelp.h"
46#endif
47
1226b3b3
WS
48#ifndef __WXMSW__
49 #include "../sample.xpm"
50#endif
51
5d7836c4
JS
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
011b3dcb
JS
74#include "wx/richtext/richtextctrl.h"
75#include "wx/richtext/richtextstyles.h"
76#include "wx/richtext/richtextxml.h"
b71e9aa4 77#include "wx/richtext/richtexthtml.h"
8c9c49a1
JS
78#include "wx/richtext/richtextformatdlg.h"
79#include "wx/richtext/richtextsymboldlg.h"
e4723634 80#include "wx/richtext/richtextstyledlg.h"
8881d9f0 81#include "wx/richtext/richtextprint.h"
cdaed652 82#include "wx/richtext/richtextimagedlg.h"
5d7836c4
JS
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
93class MyApp : public wxApp
94{
95public:
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; }
8881d9f0 108 wxRichTextPrinting* GetPrinting() const { return m_printing; }
5d7836c4 109
8881d9f0
JS
110 wxRichTextStyleSheet* m_styleSheet;
111 wxRichTextPrinting* m_printing;
5d7836c4
JS
112};
113
114// Define a new frame type: this is going to be our main frame
115class MyFrame : public wxFrame
116{
117public:
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
5d7836c4
JS
146 void OnIndentMore(wxCommandEvent& event);
147 void OnIndentLess(wxCommandEvent& event);
148
8c9c49a1 149 void OnFont(wxCommandEvent& event);
cdaed652
VZ
150 void OnImage(wxCommandEvent& event);
151 void OnUpdateImage(wxUpdateUIEvent& event);
8c9c49a1
JS
152 void OnParagraph(wxCommandEvent& event);
153 void OnFormat(wxCommandEvent& event);
154 void OnUpdateFormat(wxUpdateUIEvent& event);
155
156 void OnInsertSymbol(wxCommandEvent& event);
157
5d7836c4
JS
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
082cfe55 165 void OnNumberList(wxCommandEvent& event);
e4723634 166 void OnBulletsAndNumbering(wxCommandEvent& event);
082cfe55
JS
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
99404ab0
JS
173 void OnReload(wxCommandEvent& event);
174
5d7836c4
JS
175 void OnViewHTML(wxCommandEvent& event);
176
fe5aa22c 177 void OnSwitchStyleSheets(wxCommandEvent& event);
e4723634 178 void OnManageStyles(wxCommandEvent& event);
fe5aa22c 179
720cc10a
JS
180 void OnInsertURL(wxCommandEvent& event);
181 void OnURL(wxTextUrlEvent& event);
182 void OnStyleSheetReplacing(wxRichTextEvent& event);
183
8881d9f0
JS
184 void OnPrint(wxCommandEvent& event);
185 void OnPreview(wxCommandEvent& event);
186 void OnPageSetup(wxCommandEvent& event);
187
cdaed652 188 void OnInsertImage(wxCommandEvent& event);
004867db
FM
189protected:
190
5d7836c4
JS
191 // Forward command events to the current rich text control, if any
192 bool ProcessEvent(wxEvent& event);
193
99404ab0
JS
194 // Write text
195 void WriteInitialText();
196
5d7836c4
JS
197private:
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
209enum
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,
cdaed652 219 ID_FORMAT_IMAGE,
8c9c49a1
JS
220 ID_FORMAT_PARAGRAPH,
221 ID_FORMAT_CONTENT,
222
99404ab0
JS
223 ID_RELOAD,
224
8c9c49a1 225 ID_INSERT_SYMBOL,
720cc10a 226 ID_INSERT_URL,
cdaed652 227 ID_INSERT_IMAGE,
5d7836c4
JS
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
082cfe55 243 ID_FORMAT_NUMBER_LIST,
e4723634 244 ID_FORMAT_BULLETS_AND_NUMBERING,
082cfe55
JS
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
fe5aa22c
JS
251 ID_VIEW_HTML,
252 ID_SWITCH_STYLE_SHEETS,
e4723634 253 ID_MANAGE_STYLES,
fe5aa22c 254
8881d9f0
JS
255 ID_PRINT,
256 ID_PREVIEW,
257 ID_PAGE_SETUP,
258
fe5aa22c
JS
259 ID_RICHTEXT_CTRL,
260 ID_RICHTEXT_STYLE_LIST,
261 ID_RICHTEXT_STYLE_COMBO
5d7836c4
JS
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.
271BEGIN_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)
cdaed652 296 EVT_MENU(ID_FORMAT_IMAGE, MyFrame::OnImage)
8c9c49a1
JS
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)
cdaed652 301 EVT_UPDATE_UI(ID_FORMAT_IMAGE, MyFrame::OnUpdateImage)
8c9c49a1 302 EVT_UPDATE_UI(ID_FORMAT_PARAGRAPH, MyFrame::OnUpdateFormat)
5d7836c4
JS
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
99404ab0
JS
313 EVT_MENU(ID_RELOAD, MyFrame::OnReload)
314
8c9c49a1 315 EVT_MENU(ID_INSERT_SYMBOL, MyFrame::OnInsertSymbol)
720cc10a 316 EVT_MENU(ID_INSERT_URL, MyFrame::OnInsertURL)
cdaed652 317 EVT_MENU(ID_INSERT_IMAGE, MyFrame::OnInsertImage)
8c9c49a1 318
082cfe55 319 EVT_MENU(ID_FORMAT_NUMBER_LIST, MyFrame::OnNumberList)
e4723634 320 EVT_MENU(ID_FORMAT_BULLETS_AND_NUMBERING, MyFrame::OnBulletsAndNumbering)
082cfe55
JS
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
5d7836c4 327 EVT_MENU(ID_VIEW_HTML, MyFrame::OnViewHTML)
fe5aa22c 328 EVT_MENU(ID_SWITCH_STYLE_SHEETS, MyFrame::OnSwitchStyleSheets)
e4723634 329 EVT_MENU(ID_MANAGE_STYLES, MyFrame::OnManageStyles)
720cc10a 330
8881d9f0
JS
331 EVT_MENU(ID_PRINT, MyFrame::OnPrint)
332 EVT_MENU(ID_PREVIEW, MyFrame::OnPreview)
333 EVT_MENU(ID_PAGE_SETUP, MyFrame::OnPageSetup)
334
720cc10a
JS
335 EVT_TEXT_URL(wxID_ANY, MyFrame::OnURL)
336 EVT_RICHTEXT_STYLESHEET_REPLACING(wxID_ANY, MyFrame::OnStyleSheetReplacing)
5d7836c4
JS
337END_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)
344IMPLEMENT_APP(MyApp)
345
346// ============================================================================
347// implementation
348// ============================================================================
349
350// ----------------------------------------------------------------------------
351// the application class
352// ----------------------------------------------------------------------------
353
354// 'Main program' equivalent: the program execution "starts" here
355bool MyApp::OnInit()
356{
45e6e6f8
VZ
357 if ( !wxApp::OnInit() )
358 return false;
359
2569ebc2
JS
360#if wxUSE_HELP
361 wxHelpProvider::Set(new wxSimpleHelpProvider);
362#endif
363
5d7836c4 364 m_styleSheet = new wxRichTextStyleSheet;
8881d9f0
JS
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);
5d7836c4
JS
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
9a173d48 380
5d7836c4
JS
381#if wxUSE_LIBJPEG
382 wxImage::AddHandler( new wxJPEGHandler );
383#endif
384
385#if wxUSE_GIF
386 wxImage::AddHandler( new wxGIFHandler );
387#endif
388
720cc10a
JS
389#if wxUSE_FILESYSTEM
390 wxFileSystem::AddHandler( new wxMemoryFSHandler );
391#endif
392
5d7836c4 393 // create the main application window
9a83f860 394 MyFrame *frame = new MyFrame(wxT("wxRichTextCtrl Sample"), wxID_ANY, wxDefaultPosition, wxSize(700, 600));
5d7836c4 395
8881d9f0
JS
396 m_printing->SetParentWindow(frame);
397
5d7836c4
JS
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
408int MyApp::OnExit()
409{
8881d9f0 410 delete m_printing;
5d7836c4 411 delete m_styleSheet;
8881d9f0 412
5d7836c4
JS
413 return 0;
414}
415
416void 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);
9a173d48 432
5d7836c4
JS
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);
9a173d48 443
5d7836c4
JS
444 m_styleSheet->AddParagraphStyle(indentedPara);
445
27e20452
JS
446 wxRichTextParagraphStyleDefinition* indentedPara2 = new wxRichTextParagraphStyleDefinition(wxT("Red Bold Indented"));
447 wxRichTextAttr indentedAttr2;
448 indentedAttr2.SetFontFaceName(romanFont.GetFaceName());
449 indentedAttr2.SetFontSize(12);
00621a0d 450 indentedAttr2.SetFontWeight(wxFONTWEIGHT_BOLD);
27e20452
JS
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
5d7836c4
JS
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);
9a173d48 468
5d7836c4
JS
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);
00621a0d 477 boldAttr.SetFontWeight(wxFONTWEIGHT_BOLD);
5d7836c4
JS
478 // We only want to affect boldness
479 boldAttr.SetFlags(wxTEXT_ATTR_FONT_WEIGHT);
480 boldDef->SetStyle(boldAttr);
9a173d48 481
5d7836c4
JS
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);
00621a0d 488 italicAttr.SetFontStyle(wxFONTSTYLE_ITALIC);
5d7836c4
JS
489 // We only want to affect italics
490 italicAttr.SetFlags(wxTEXT_ATTR_FONT_ITALIC);
491 italicDef->SetStyle(italicAttr);
9a173d48 492
5d7836c4
JS
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);
00621a0d 499 redAttr.SetFontWeight(wxFONTWEIGHT_BOLD);
5d7836c4
JS
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);
9a173d48 504
5d7836c4 505 m_styleSheet->AddCharacterStyle(redDef);
082cfe55
JS
506
507 wxRichTextListStyleDefinition* bulletList = new wxRichTextListStyleDefinition(wxT("Bullet List 1"));
508 int i;
509 for (i = 0; i < 10; i++)
510 {
720cc10a 511 wxString bulletText;
082cfe55 512 if (i == 0)
720cc10a 513 bulletText = wxT("standard/circle");
082cfe55 514 else if (i == 1)
720cc10a 515 bulletText = wxT("standard/square");
082cfe55 516 else if (i == 2)
720cc10a 517 bulletText = wxT("standard/circle");
082cfe55 518 else if (i == 3)
720cc10a 519 bulletText = wxT("standard/square");
082cfe55 520 else
720cc10a 521 bulletText = wxT("standard/circle");
082cfe55 522
720cc10a 523 bulletList->SetAttributes(i, (i+1)*60, 60, wxTEXT_ATTR_BULLET_STYLE_STANDARD, bulletText);
082cfe55
JS
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
720cc10a
JS
543 numberStyle |= wxTEXT_ATTR_BULLET_STYLE_ALIGN_RIGHT;
544
082cfe55
JS
545 numberedList->SetAttributes(i, (i+1)*60, 60, numberStyle);
546 }
547
548 m_styleSheet->AddListStyle(numberedList);
720cc10a
JS
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);
5d7836c4
JS
563}
564
565// ----------------------------------------------------------------------------
566// main frame
567// ----------------------------------------------------------------------------
568
569// frame constructor
570MyFrame::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
1226b3b3 575 SetIcon(wxICON(sample));
5d7836c4
JS
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;
9a83f860 582 helpMenu->Append(ID_About, wxT("&About...\tF1"), wxT("Show about dialog"));
5d7836c4 583
9a83f860
VZ
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"));
5d7836c4 587 fileMenu->AppendSeparator();
9a83f860 588 fileMenu->Append(ID_RELOAD, wxT("&Reload Text\tF2"), wxT("Reload the initial text"));
99404ab0 589 fileMenu->AppendSeparator();
9a83f860
VZ
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"));
8881d9f0 593 fileMenu->AppendSeparator();
9a83f860 594 fileMenu->Append(ID_VIEW_HTML, wxT("&View as HTML"), wxT("View HTML"));
5d7836c4 595 fileMenu->AppendSeparator();
9a83f860 596 fileMenu->Append(ID_Quit, wxT("E&xit\tAlt+X"), wxT("Quit this program"));
5d7836c4
JS
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
5d7836c4
JS
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();
c4cd20cf 623 formatMenu->Append(ID_FORMAT_INDENT_MORE, _("Indent &More"));
5d7836c4
JS
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..."));
cdaed652 634 formatMenu->Append(ID_FORMAT_IMAGE, _("Image Property"));
8c9c49a1
JS
635 formatMenu->Append(ID_FORMAT_PARAGRAPH, _("&Paragraph..."));
636 formatMenu->Append(ID_FORMAT_CONTENT, _("Font and Pa&ragraph...\tShift+Ctrl+F"));
fe5aa22c
JS
637 formatMenu->AppendSeparator();
638 formatMenu->Append(ID_SWITCH_STYLE_SHEETS, _("&Switch Style Sheets"));
e4723634
JS
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"));
5d7836c4 650
8c9c49a1
JS
651 wxMenu* insertMenu = new wxMenu;
652 insertMenu->Append(ID_INSERT_SYMBOL, _("&Symbol...\tCtrl+I"));
720cc10a 653 insertMenu->Append(ID_INSERT_URL, _("&URL..."));
cdaed652 654 insertMenu->Append(ID_INSERT_IMAGE, _("&Image..."));
8c9c49a1 655
5d7836c4
JS
656 // now append the freshly created menu to the menu bar...
657 wxMenuBar *menuBar = new wxMenuBar();
9a83f860
VZ
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"));
5d7836c4
JS
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)
4753c7ce
WS
669 // but don't create it on limited screen space (WinCE)
670 bool is_pda = wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA;
671
9a173d48 672#if wxUSE_STATUSBAR
4753c7ce
WS
673 if ( !is_pda )
674 {
675 CreateStatusBar(2);
9a83f860 676 SetStatusText(wxT("Welcome to wxRichTextCtrl!"));
4753c7ce 677 }
9a173d48 678#endif
5d7836c4
JS
679
680 wxToolBar* toolBar = CreateToolBar();
681
bbe28fbb
PC
682 toolBar->AddTool(wxID_OPEN, wxEmptyString, wxBitmap(open_xpm), _("Open"));
683 toolBar->AddTool(wxID_SAVEAS, wxEmptyString, wxBitmap(save_xpm), _("Save"));
5d7836c4 684 toolBar->AddSeparator();
bbe28fbb
PC
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"));
5d7836c4 688 toolBar->AddSeparator();
bbe28fbb
PC
689 toolBar->AddTool(wxID_UNDO, wxEmptyString, wxBitmap(undo_xpm), _("Undo"));
690 toolBar->AddTool(wxID_REDO, wxEmptyString, wxBitmap(redo_xpm), _("Redo"));
5d7836c4 691 toolBar->AddSeparator();
bbe28fbb
PC
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"));
5d7836c4 695 toolBar->AddSeparator();
bbe28fbb
PC
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"));
5d7836c4 699 toolBar->AddSeparator();
bbe28fbb
PC
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"));
5d7836c4 702 toolBar->AddSeparator();
bbe28fbb 703 toolBar->AddTool(ID_FORMAT_FONT, wxEmptyString, wxBitmap(font_xpm), _("Font"));
cdaed652 704 toolBar->AddTool(ID_FORMAT_IMAGE, wxString("Im"), wxBitmap(font_xpm), _("Image Property"));
5d7836c4 705
fe5aa22c 706 wxRichTextStyleComboCtrl* combo = new wxRichTextStyleComboCtrl(toolBar, ID_RICHTEXT_STYLE_COMBO, wxDefaultPosition, wxSize(200, -1));
e637208a
JS
707 toolBar->AddControl(combo);
708
5d7836c4
JS
709 toolBar->Realize();
710
a047aff2 711 wxSplitterWindow* splitter = new wxSplitterWindow(this, wxID_ANY, wxDefaultPosition, GetClientSize(), wxSP_LIVE_UPDATE);
5d7836c4
JS
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
a047aff2 717 m_richTextCtrl = new wxRichTextCtrl(splitter, ID_RICHTEXT_CTRL, wxEmptyString, wxDefaultPosition, wxSize(200, 200), wxVSCROLL|wxHSCROLL|wxWANTS_CHARS);
ff2baa25
JS
718 wxFont font(12, wxROMAN, wxNORMAL, wxNORMAL);
719
ff2baa25 720 m_richTextCtrl->SetFont(font);
5d7836c4 721
603f702b
JS
722 m_richTextCtrl->SetMargins(10, 10);
723
fe5aa22c
JS
724 m_richTextCtrl->SetStyleSheet(wxGetApp().GetStyleSheet());
725
e637208a
JS
726 combo->SetStyleSheet(wxGetApp().GetStyleSheet());
727 combo->SetRichTextCtrl(m_richTextCtrl);
728 combo->UpdateStyles();
729
082cfe55 730 wxRichTextStyleListCtrl* styleListCtrl = new wxRichTextStyleListCtrl(splitter, ID_RICHTEXT_STYLE_LIST);
4753c7ce
WS
731
732 wxSize display = wxGetDisplaySize();
733 if ( is_pda && ( display.GetWidth() < display.GetHeight() ) )
734 {
082cfe55 735 splitter->SplitHorizontally(m_richTextCtrl, styleListCtrl);
4753c7ce
WS
736 }
737 else
738 {
082cfe55 739 splitter->SplitVertically(m_richTextCtrl, styleListCtrl, 500);
4753c7ce 740 }
5d7836c4 741
c59f6793
JS
742 splitter->UpdateSize();
743
082cfe55
JS
744 styleListCtrl->SetStyleSheet(wxGetApp().GetStyleSheet());
745 styleListCtrl->SetRichTextCtrl(m_richTextCtrl);
746 styleListCtrl->UpdateStyles();
5d7836c4 747
99404ab0
JS
748 WriteInitialText();
749}
750
751// Write text
752void MyFrame::WriteInitialText()
753{
5d7836c4
JS
754 wxRichTextCtrl& r = *m_richTextCtrl;
755
99404ab0
JS
756 r.SetDefaultStyle(wxRichTextAttr());
757
5d7836c4
JS
758 r.BeginSuppressUndo();
759
cdaed652
VZ
760 r.Freeze();
761
603f702b 762#if 1
5d7836c4
JS
763 r.BeginParagraphSpacing(0, 20);
764
765 r.BeginAlignment(wxTEXT_ALIGNMENT_CENTRE);
766 r.BeginBold();
767
768 r.BeginFontSize(14);
c3e54dee 769
50f65288 770 wxString lineBreak = (wxChar) 29;
c3e54dee 771
99404ab0 772 r.WriteText(wxString(wxT("Welcome to wxRichTextCtrl, a wxWidgets control")) + lineBreak + wxT("for editing and presenting styled text and images\n"));
5d7836c4 773 r.EndFontSize();
5d7836c4
JS
774
775 r.BeginItalic();
776 r.WriteText(wxT("by Julian Smart"));
777 r.EndItalic();
778
779 r.EndBold();
5d7836c4 780 r.Newline();
42688aea 781
5d7836c4
JS
782 r.WriteImage(wxBitmap(zebra_xpm));
783
5d7836c4
JS
784 r.Newline();
785 r.Newline();
786
99404ab0
JS
787 r.EndAlignment();
788
cdaed652 789 r.BeginAlignment(wxTEXT_ALIGNMENT_LEFT);
24777478
JS
790 wxRichTextAttr imageAttr;
791 imageAttr.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_LEFT);
cdaed652 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.")));
24777478
JS
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);
5ad9ae3a 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.")));
cdaed652
VZ
799 r.EndAlignment();
800 r.Newline();
801
5d7836c4 802 r.WriteText(wxT("What can you do with this thing? "));
42688aea 803
5d7836c4
JS
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
3e541562
JS
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();
5d7836c4
JS
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
5d7836c4
JS
835 r.Newline();
836
99404ab0 837 r.BeginLeftIndent(60);
5d7836c4 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."));
5d7836c4
JS
839 r.Newline();
840
99404ab0
JS
841 r.EndLeftIndent();
842
5d7836c4
JS
843 r.WriteText(wxT("Next, we'll show a first-line indent, achieved using BeginLeftIndent(100, -40)."));
844
5d7836c4
JS
845 r.Newline();
846
99404ab0 847 r.BeginLeftIndent(100, -40);
5d7836c4 848
99404ab0 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."));
5d7836c4
JS
850 r.Newline();
851
99404ab0 852 r.EndLeftIndent();
5d7836c4 853
99404ab0 854 r.WriteText(wxT("Numbered bullets are possible, again using subindents:"));
5d7836c4
JS
855 r.Newline();
856
99404ab0 857 r.BeginNumberedBullet(1, 100, 60);
082cfe55 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."));
99404ab0 859 r.Newline();
5d7836c4
JS
860 r.EndNumberedBullet();
861
862 r.BeginNumberedBullet(2, 100, 60);
5d7836c4 863 r.WriteText(wxT("This is my second item."));
5d7836c4 864 r.Newline();
99404ab0 865 r.EndNumberedBullet();
5d7836c4
JS
866
867 r.WriteText(wxT("The following paragraph is right-indented:"));
99404ab0 868 r.Newline();
5d7836c4
JS
869
870 r.BeginRightIndent(200);
5d7836c4
JS
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."));
5d7836c4
JS
873 r.Newline();
874
99404ab0
JS
875 r.EndRightIndent();
876
5d7836c4 877 r.WriteText(wxT("The following paragraph is right-aligned with 1.5 line spacing:"));
99404ab0 878 r.Newline();
5d7836c4
JS
879
880 r.BeginAlignment(wxTEXT_ALIGNMENT_RIGHT);
881 r.BeginLineSpacing(wxTEXT_ATTR_LINE_SPACING_HALF);
5d7836c4 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."));
99404ab0 883 r.Newline();
5d7836c4
JS
884 r.EndLineSpacing();
885 r.EndAlignment();
886
7f0d9d71
JS
887 wxArrayInt tabs;
888 tabs.Add(400);
889 tabs.Add(600);
890 tabs.Add(800);
891 tabs.Add(1000);
24777478 892 wxRichTextAttr attr;
7f0d9d71
JS
893 attr.SetFlags(wxTEXT_ATTR_TABS);
894 attr.SetTabs(tabs);
895 r.SetDefaultStyle(attr);
4753c7ce 896
7f0d9d71 897 r.WriteText(wxT("This line contains tabs:\tFirst tab\tSecond tab\tThird tab"));
5d7836c4 898 r.Newline();
99404ab0 899
5d7836c4 900 r.WriteText(wxT("Other notable features of wxRichTextCtrl include:"));
99404ab0 901 r.Newline();
5d7836c4
JS
902
903 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 904 r.WriteText(wxT("Compatibility with wxTextCtrl API"));
99404ab0 905 r.Newline();
5d7836c4
JS
906 r.EndSymbolBullet();
907
908 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 909 r.WriteText(wxT("Easy stack-based BeginXXX()...EndXXX() style setting in addition to SetStyle()"));
99404ab0 910 r.Newline();
5d7836c4
JS
911 r.EndSymbolBullet();
912
913 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 914 r.WriteText(wxT("XML loading and saving"));
99404ab0 915 r.Newline();
5d7836c4
JS
916 r.EndSymbolBullet();
917
918 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 919 r.WriteText(wxT("Undo/Redo, with batching option and Undo suppressing"));
99404ab0 920 r.Newline();
5d7836c4
JS
921 r.EndSymbolBullet();
922
923 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 924 r.WriteText(wxT("Clipboard copy and paste"));
99404ab0 925 r.Newline();
5d7836c4
JS
926 r.EndSymbolBullet();
927
928 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 929 r.WriteText(wxT("wxRichTextStyleSheet with named character and paragraph styles, and control for applying named styles"));
99404ab0 930 r.Newline();
5d7836c4
JS
931 r.EndSymbolBullet();
932
933 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 934 r.WriteText(wxT("A design that can easily be extended to other content types, ultimately with text boxes, tables, controls, and so on"));
5d7836c4 935 r.Newline();
99404ab0 936 r.EndSymbolBullet();
5d7836c4 937
720cc10a
JS
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
99404ab0 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"));
5d7836c4
JS
954
955 r.EndParagraphSpacing();
603f702b
JS
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);
5d7836c4 969
603f702b
JS
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
cdaed652
VZ
1019 r.Thaw();
1020
5d7836c4
JS
1021 r.EndSuppressUndo();
1022}
1023
5d7836c4
JS
1024// event handlers
1025
1026void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
1027{
1028 // true is to force the frame to close
1029 Close(true);
1030}
1031
1032void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
1033{
1034 wxString msg;
9a83f860
VZ
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);
5d7836c4
JS
1037}
1038
1039// Forward command events to the current rich text control, if any
1040bool 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();
9a173d48 1056
5d7836c4 1057 wxWindow* focusWin = wxFindFocusDescendant(this);
004867db 1058 if (focusWin && focusWin->GetEventHandler()->ProcessEvent(event))
5d7836c4
JS
1059 {
1060 //s_command = NULL;
1061 s_eventType = 0;
1062 s_id = 0;
9a173d48 1063 return true;
5d7836c4
JS
1064 }
1065
1066 s_eventType = 0;
1067 s_id = 0;
1068 }
1069 else
1070 {
9a173d48 1071 return false;
5d7836c4
JS
1072 }
1073 }
1074
1075 return wxFrame::ProcessEvent(event);
1076}
1077
011b3dcb 1078void MyFrame::OnOpen(wxCommandEvent& WXUNUSED(event))
5d7836c4 1079{
9a173d48
WS
1080 wxString path;
1081 wxString filename;
1e967276
JS
1082 wxArrayInt fileTypes;
1083
1084 wxString filter = wxRichTextBuffer::GetExtWildcard(false, false, & fileTypes);
9a173d48 1085 if (!filter.empty())
5d7836c4
JS
1086 filter += wxT("|");
1087 filter += wxT("All files (*.*)|*.*");
1088
5d7836c4
JS
1089 wxFileDialog dialog(this,
1090 _("Choose a filename"),
1091 path,
1092 filename,
1093 filter,
ff3e84ff 1094 wxFD_OPEN);
5d7836c4
JS
1095
1096 if (dialog.ShowModal() == wxID_OK)
1097 {
1098 wxString path = dialog.GetPath();
9a173d48
WS
1099
1100 if (!path.empty())
5d7836c4 1101 {
1e967276 1102 int filterIndex = dialog.GetFilterIndex();
dbf38e88
WS
1103 int fileType = (filterIndex < (int) fileTypes.GetCount())
1104 ? fileTypes[filterIndex]
1105 : wxRICHTEXT_TYPE_TEXT;
1e967276 1106 m_richTextCtrl->LoadFile(path, fileType);
5d7836c4
JS
1107 }
1108 }
1109}
1110
1111void MyFrame::OnSave(wxCommandEvent& event)
1112{
9a173d48 1113 if (m_richTextCtrl->GetFilename().empty())
5d7836c4
JS
1114 {
1115 OnSaveAs(event);
1116 return;
1117 }
1118 m_richTextCtrl->SaveFile();
1119}
1120
011b3dcb 1121void MyFrame::OnSaveAs(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1122{
1123 wxString filter = wxRichTextBuffer::GetExtWildcard(false, true);
9a173d48
WS
1124 wxString path;
1125 wxString filename;
5d7836c4
JS
1126
1127 wxFileDialog dialog(this,
1128 _("Choose a filename"),
1129 path,
1130 filename,
1131 filter,
ff3e84ff 1132 wxFD_SAVE);
5d7836c4
JS
1133
1134 if (dialog.ShowModal() == wxID_OK)
1135 {
1136 wxString path = dialog.GetPath();
9a173d48
WS
1137
1138 if (!path.empty())
5d7836c4 1139 {
bec80f4f
JS
1140 wxBusyCursor busy;
1141 wxStopWatch stopwatch;
1142
5d7836c4 1143 m_richTextCtrl->SaveFile(path);
bec80f4f
JS
1144
1145 long t = stopwatch.Time();
1146 wxLogDebug(wxT("Saving took %ldms"), t);
1147 wxMessageBox(wxString::Format(wxT("Saving took %ldms"), t));
5d7836c4
JS
1148 }
1149 }
1150}
1151
011b3dcb 1152void MyFrame::OnBold(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1153{
1154 m_richTextCtrl->ApplyBoldToSelection();
1155}
1156
011b3dcb 1157void MyFrame::OnItalic(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1158{
1159 m_richTextCtrl->ApplyItalicToSelection();
1160}
1161
011b3dcb 1162void MyFrame::OnUnderline(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1163{
1164 m_richTextCtrl->ApplyUnderlineToSelection();
1165}
1166
1167
1168void MyFrame::OnUpdateBold(wxUpdateUIEvent& event)
1169{
1170 event.Check(m_richTextCtrl->IsSelectionBold());
1171}
1172
1173void MyFrame::OnUpdateItalic(wxUpdateUIEvent& event)
1174{
1175 event.Check(m_richTextCtrl->IsSelectionItalics());
1176}
1177
1178void MyFrame::OnUpdateUnderline(wxUpdateUIEvent& event)
1179{
1180 event.Check(m_richTextCtrl->IsSelectionUnderlined());
1181}
1182
011b3dcb 1183void MyFrame::OnAlignLeft(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1184{
1185 m_richTextCtrl->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_LEFT);
1186}
1187
011b3dcb 1188void MyFrame::OnAlignCentre(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1189{
1190 m_richTextCtrl->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_CENTRE);
1191}
1192
011b3dcb 1193void MyFrame::OnAlignRight(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1194{
1195 m_richTextCtrl->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_RIGHT);
1196}
1197
1198void MyFrame::OnUpdateAlignLeft(wxUpdateUIEvent& event)
1199{
1200 event.Check(m_richTextCtrl->IsSelectionAligned(wxTEXT_ALIGNMENT_LEFT));
1201}
1202
1203void MyFrame::OnUpdateAlignCentre(wxUpdateUIEvent& event)
1204{
1205 event.Check(m_richTextCtrl->IsSelectionAligned(wxTEXT_ALIGNMENT_CENTRE));
1206}
1207
1208void MyFrame::OnUpdateAlignRight(wxUpdateUIEvent& event)
1209{
1210 event.Check(m_richTextCtrl->IsSelectionAligned(wxTEXT_ALIGNMENT_RIGHT));
1211}
1212
011b3dcb 1213void MyFrame::OnFont(wxCommandEvent& WXUNUSED(event))
5d7836c4 1214{
8c9c49a1
JS
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 {
42688aea 1228 formatDlg.ApplyStyle(m_richTextCtrl, range, wxRICHTEXT_SETSTYLE_WITH_UNDO|wxRICHTEXT_SETSTYLE_OPTIMIZE|wxRICHTEXT_SETSTYLE_CHARACTERS_ONLY);
8c9c49a1
JS
1229 }
1230
1231 // Old method using wxFontDialog
1232#if 0
5d7836c4
JS
1233 if (!m_richTextCtrl->HasSelection())
1234 return;
1235
1236 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1237 wxFontData fontData;
1238
24777478 1239 wxRichTextAttr attr;
5d7836c4
JS
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());
a1b806b9 1251 if (attr.GetFont().IsOk())
5d7836c4
JS
1252 {
1253 m_richTextCtrl->SetStyle(range, attr);
1254 }
1255 }
8c9c49a1
JS
1256#endif
1257}
1258
cdaed652
VZ
1259void 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
603f702b 1267 wxRichTextImage* image = wxDynamicCast(m_richTextCtrl->GetFocusObject()->GetLeafObjectAtPosition(range.GetStart()), wxRichTextImage);
cdaed652
VZ
1268 if (image)
1269 {
603f702b 1270 wxRichTextObjectPropertiesDialog imageDlg(image, this);
cdaed652
VZ
1271
1272 if (imageDlg.ShowModal() == wxID_OK)
1273 {
603f702b 1274 imageDlg.ApplyStyle(m_richTextCtrl);
cdaed652
VZ
1275 }
1276 }
1277}
1278
8c9c49a1
JS
1279void 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
1298void 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
1317void MyFrame::OnUpdateFormat(wxUpdateUIEvent& event)
1318{
1319 event.Enable(m_richTextCtrl->HasSelection());
5d7836c4
JS
1320}
1321
cdaed652
VZ
1322void MyFrame::OnUpdateImage(wxUpdateUIEvent& event)
1323{
1324 wxRichTextRange range;
1325 wxRichTextObject *obj;
1326
1327 range = m_richTextCtrl->GetSelectionRange();
1328 if (range.ToInternal().GetLength() == 1)
1329 {
603f702b 1330 obj = m_richTextCtrl->GetFocusObject()->GetLeafObjectAtPosition(range.GetStart());
cdaed652
VZ
1331 if (obj && obj->IsKindOf(CLASSINFO(wxRichTextImage)))
1332 {
1333 event.Enable(true);
1334 return;
1335 }
1336 }
1337
1338 event.Enable(false);
1339}
1340
011b3dcb 1341void MyFrame::OnIndentMore(wxCommandEvent& WXUNUSED(event))
5d7836c4 1342{
44cc96a8 1343 wxRichTextAttr attr;
5d7836c4
JS
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
5d7836c4
JS
1352 attr.SetLeftIndent(attr.GetLeftIndent() + 100);
1353
1354 attr.SetFlags(wxTEXT_ATTR_LEFT_INDENT);
1355 m_richTextCtrl->SetStyle(range, attr);
1356 }
1357}
1358
011b3dcb 1359void MyFrame::OnIndentLess(wxCommandEvent& WXUNUSED(event))
5d7836c4 1360{
44cc96a8 1361 wxRichTextAttr attr;
5d7836c4
JS
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
c3e54dee 1370 if (attr.GetLeftIndent() > 0)
5d7836c4 1371 {
c3e54dee 1372 attr.SetLeftIndent(wxMax(0, attr.GetLeftIndent() - 100));
9a173d48 1373
5d7836c4
JS
1374 m_richTextCtrl->SetStyle(range, attr);
1375 }
1376 }
1377}
1378
011b3dcb 1379void MyFrame::OnLineSpacingHalf(wxCommandEvent& WXUNUSED(event))
5d7836c4 1380{
44cc96a8 1381 wxRichTextAttr attr;
5d7836c4
JS
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
5d7836c4
JS
1390 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1391 attr.SetLineSpacing(15);
9a173d48 1392
5d7836c4
JS
1393 m_richTextCtrl->SetStyle(range, attr);
1394 }
1395}
1396
011b3dcb 1397void MyFrame::OnLineSpacingDouble(wxCommandEvent& WXUNUSED(event))
5d7836c4 1398{
44cc96a8 1399 wxRichTextAttr attr;
5d7836c4
JS
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
5d7836c4
JS
1408 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1409 attr.SetLineSpacing(20);
9a173d48 1410
5d7836c4
JS
1411 m_richTextCtrl->SetStyle(range, attr);
1412 }
1413}
1414
011b3dcb 1415void MyFrame::OnLineSpacingSingle(wxCommandEvent& WXUNUSED(event))
5d7836c4 1416{
44cc96a8 1417 wxRichTextAttr attr;
5d7836c4
JS
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
5d7836c4
JS
1426 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1427 attr.SetLineSpacing(0); // Can also use 10
9a173d48 1428
5d7836c4
JS
1429 m_richTextCtrl->SetStyle(range, attr);
1430 }
1431}
1432
011b3dcb 1433void MyFrame::OnParagraphSpacingMore(wxCommandEvent& WXUNUSED(event))
5d7836c4 1434{
44cc96a8 1435 wxRichTextAttr attr;
5d7836c4
JS
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
5d7836c4
JS
1444 attr.SetParagraphSpacingAfter(attr.GetParagraphSpacingAfter() + 20);
1445
1446 attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER);
1447 m_richTextCtrl->SetStyle(range, attr);
1448 }
1449}
1450
011b3dcb 1451void MyFrame::OnParagraphSpacingLess(wxCommandEvent& WXUNUSED(event))
5d7836c4 1452{
44cc96a8 1453 wxRichTextAttr attr;
5d7836c4
JS
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 {
5d7836c4 1464 attr.SetParagraphSpacingAfter(attr.GetParagraphSpacingAfter() - 20);
9a173d48 1465
5d7836c4
JS
1466 attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER);
1467 m_richTextCtrl->SetStyle(range, attr);
1468 }
1469 }
1470}
1471
99404ab0
JS
1472void MyFrame::OnReload(wxCommandEvent& WXUNUSED(event))
1473{
1474 m_richTextCtrl->Clear();
1475 WriteInitialText();
1476}
1477
011b3dcb 1478void MyFrame::OnViewHTML(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
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;
720cc10a 1495 htmlHandler.SetFlags(wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_MEMORY);
c3e54dee 1496
50f65288
WS
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);
c3e54dee 1505
50f65288 1506 htmlHandler.SetFontSizeMapping(fontSizeMapping);
720cc10a 1507
5d7836c4
JS
1508 if (htmlHandler.SaveFile(& m_richTextCtrl->GetBuffer(), strStream))
1509 {
1510 win->SetPage(text);
1511 }
1512
1513 boxSizer->Fit(& dialog);
1514
1515 dialog.ShowModal();
720cc10a
JS
1516
1517 // Now delete the temporary in-memory images
1518 htmlHandler.DeleteTemporaryImages();
5d7836c4 1519}
fe5aa22c
JS
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
1524void MyFrame::OnSwitchStyleSheets(wxCommandEvent& WXUNUSED(event))
1525{
1526 static wxRichTextStyleSheet* gs_AlternateStyleSheet = NULL;
1527
e4723634 1528 wxRichTextStyleListCtrl *styleList = (wxRichTextStyleListCtrl*) FindWindow(ID_RICHTEXT_STYLE_LIST);
fe5aa22c
JS
1529 wxRichTextStyleComboCtrl* styleCombo = (wxRichTextStyleComboCtrl*) FindWindow(ID_RICHTEXT_STYLE_COMBO);
1530
8881d9f0 1531 wxRichTextStyleSheet* sheet = m_richTextCtrl->GetStyleSheet();
fe5aa22c
JS
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
8881d9f0
JS
1565 m_richTextCtrl->SetStyleSheet(sheet);
1566 m_richTextCtrl->ApplyStyleSheet(sheet); // Makes the control reflect the new style definitions
fe5aa22c
JS
1567
1568 styleList->SetStyleSheet(sheet);
1569 styleList->UpdateStyles();
1570
1571 styleCombo->SetStyleSheet(sheet);
1572 styleCombo->UpdateStyles();
1573}
8c9c49a1 1574
e4723634
JS
1575void MyFrame::OnManageStyles(wxCommandEvent& WXUNUSED(event))
1576{
8881d9f0 1577 wxRichTextStyleSheet* sheet = m_richTextCtrl->GetStyleSheet();
e4723634
JS
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
8c9c49a1
JS
1585void MyFrame::OnInsertSymbol(wxCommandEvent& WXUNUSED(event))
1586{
44cc96a8 1587 wxRichTextAttr attr;
8c9c49a1 1588 attr.SetFlags(wxTEXT_ATTR_FONT);
8881d9f0 1589 m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr);
8c9c49a1
JS
1590
1591 wxString currentFontName;
a1b806b9 1592 if (attr.HasFont() && attr.GetFont().IsOk())
8c9c49a1
JS
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 {
8881d9f0 1605 long insertionPoint = m_richTextCtrl->GetInsertionPoint();
8c9c49a1 1606
8881d9f0 1607 m_richTextCtrl->WriteText(dlg.GetSymbol());
8c9c49a1
JS
1608
1609 if (!dlg.UseNormalFont())
1610 {
1611 wxFont font(attr.GetFont());
23c386ba 1612 font.SetFaceName(dlg.GetFontName());
8c9c49a1 1613 attr.SetFont(font);
8881d9f0 1614 m_richTextCtrl->SetStyle(insertionPoint, insertionPoint+1, attr);
8c9c49a1
JS
1615 }
1616 }
1617 }
1618}
082cfe55
JS
1619
1620void MyFrame::OnNumberList(wxCommandEvent& WXUNUSED(event))
1621{
8881d9f0 1622 if (m_richTextCtrl->HasSelection())
082cfe55 1623 {
8881d9f0
JS
1624 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1625 m_richTextCtrl->SetListStyle(range, wxT("Numbered List 1"), wxRICHTEXT_SETSTYLE_WITH_UNDO|wxRICHTEXT_SETSTYLE_RENUMBER);
082cfe55
JS
1626 }
1627}
1628
e4723634
JS
1629void MyFrame::OnBulletsAndNumbering(wxCommandEvent& WXUNUSED(event))
1630{
8881d9f0 1631 wxRichTextStyleSheet* sheet = m_richTextCtrl->GetStyleSheet();
e4723634
JS
1632
1633 int flags = wxRICHTEXT_ORGANISER_BROWSE_NUMBERING;
1634
8881d9f0 1635 wxRichTextStyleOrganiserDialog dlg(flags, sheet, m_richTextCtrl, this, wxID_ANY, _("Bullets and Numbering"));
e4723634
JS
1636 if (dlg.ShowModal() == wxID_OK)
1637 {
1638 if (dlg.GetSelectedStyleDefinition())
1639 dlg.ApplyStyle();
1640 }
1641}
1642
082cfe55
JS
1643void MyFrame::OnItemizeList(wxCommandEvent& WXUNUSED(event))
1644{
8881d9f0 1645 if (m_richTextCtrl->HasSelection())
082cfe55 1646 {
8881d9f0
JS
1647 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1648 m_richTextCtrl->SetListStyle(range, wxT("Bullet List 1"));
082cfe55
JS
1649 }
1650}
1651
1652void MyFrame::OnRenumberList(wxCommandEvent& WXUNUSED(event))
1653{
8881d9f0 1654 if (m_richTextCtrl->HasSelection())
082cfe55 1655 {
8881d9f0
JS
1656 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1657 m_richTextCtrl->NumberList(range, NULL, wxRICHTEXT_SETSTYLE_WITH_UNDO|wxRICHTEXT_SETSTYLE_RENUMBER);
082cfe55
JS
1658 }
1659}
1660
1661void MyFrame::OnPromoteList(wxCommandEvent& WXUNUSED(event))
1662{
8881d9f0 1663 if (m_richTextCtrl->HasSelection())
082cfe55 1664 {
8881d9f0
JS
1665 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1666 m_richTextCtrl->PromoteList(1, range, NULL);
082cfe55
JS
1667 }
1668}
1669
1670void MyFrame::OnDemoteList(wxCommandEvent& WXUNUSED(event))
1671{
8881d9f0 1672 if (m_richTextCtrl->HasSelection())
082cfe55 1673 {
8881d9f0
JS
1674 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1675 m_richTextCtrl->PromoteList(-1, range, NULL);
082cfe55
JS
1676 }
1677}
1678
1679void MyFrame::OnClearList(wxCommandEvent& WXUNUSED(event))
1680{
8881d9f0 1681 if (m_richTextCtrl->HasSelection())
082cfe55 1682 {
8881d9f0
JS
1683 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1684 m_richTextCtrl->ClearListStyle(range);
082cfe55
JS
1685 }
1686}
1687
720cc10a
JS
1688void MyFrame::OnInsertURL(wxCommandEvent& WXUNUSED(event))
1689{
1690 wxString url = wxGetTextFromUser(_("URL:"), _("Insert URL"));
1691 if (!url.IsEmpty())
1692 {
720cc10a
JS
1693 // Make a style suitable for showing a URL
1694 wxRichTextAttr urlStyle;
1695 urlStyle.SetTextColour(*wxBLUE);
1696 urlStyle.SetFontUnderlined(true);
c3e54dee 1697
8881d9f0
JS
1698 m_richTextCtrl->BeginStyle(urlStyle);
1699 m_richTextCtrl->BeginURL(url);
1700 m_richTextCtrl->WriteText(url);
1701 m_richTextCtrl->EndURL();
1702 m_richTextCtrl->EndStyle();
720cc10a
JS
1703 }
1704}
1705
cdaed652
VZ
1706void 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
720cc10a
JS
1716void 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.
1723void MyFrame::OnStyleSheetReplacing(wxRichTextEvent& event)
1724{
1725 event.Veto();
1726}
8881d9f0
JS
1727
1728void MyFrame::OnPrint(wxCommandEvent& WXUNUSED(event))
1729{
1730 wxGetApp().GetPrinting()->PrintBuffer(m_richTextCtrl->GetBuffer());
1731}
1732
1733void MyFrame::OnPreview(wxCommandEvent& WXUNUSED(event))
1734{
1735 wxGetApp().GetPrinting()->PreviewBuffer(m_richTextCtrl->GetBuffer());
1736}
1737
1738void MyFrame::OnPageSetup(wxCommandEvent& WXUNUSED(event))
1739{
24777478
JS
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
d275b15d 1746 new wxRichTextCtrl(panel, wxID_ANY, wxEmptyString, wxPoint(5, 5), wxSize(200, 150), wxVSCROLL|wxTE_READONLY);
24777478
JS
1747 nb->AddPage(panel, wxT("Page 1"));
1748
d275b15d 1749 new wxRichTextCtrl(panel2, wxID_ANY, wxEmptyString, wxPoint(5, 5), wxSize(200, 150), wxVSCROLL|wxTE_READONLY);
24777478
JS
1750 nb->AddPage(panel2, wxT("Page 2"));
1751
d275b15d 1752 new wxButton(& dialog, wxID_OK, wxT("OK"), wxPoint(5, 180));
24777478
JS
1753
1754 dialog.ShowModal();
1755
1756// wxGetApp().GetPrinting()->PageSetup();
8881d9f0 1757}