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