]> git.saurik.com Git - wxWidgets.git/blame - samples/richtext/richtext.cpp
add src/gtk1/mnemonics.cpp to files.bkl and rebake
[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
fe5aa22c
JS
722 m_richTextCtrl->SetStyleSheet(wxGetApp().GetStyleSheet());
723
e637208a
JS
724 combo->SetStyleSheet(wxGetApp().GetStyleSheet());
725 combo->SetRichTextCtrl(m_richTextCtrl);
726 combo->UpdateStyles();
727
082cfe55 728 wxRichTextStyleListCtrl* styleListCtrl = new wxRichTextStyleListCtrl(splitter, ID_RICHTEXT_STYLE_LIST);
4753c7ce
WS
729
730 wxSize display = wxGetDisplaySize();
731 if ( is_pda && ( display.GetWidth() < display.GetHeight() ) )
732 {
082cfe55 733 splitter->SplitHorizontally(m_richTextCtrl, styleListCtrl);
4753c7ce
WS
734 }
735 else
736 {
082cfe55 737 splitter->SplitVertically(m_richTextCtrl, styleListCtrl, 500);
4753c7ce 738 }
5d7836c4 739
c59f6793
JS
740 splitter->UpdateSize();
741
082cfe55
JS
742 styleListCtrl->SetStyleSheet(wxGetApp().GetStyleSheet());
743 styleListCtrl->SetRichTextCtrl(m_richTextCtrl);
744 styleListCtrl->UpdateStyles();
5d7836c4 745
99404ab0
JS
746 WriteInitialText();
747}
748
749// Write text
750void MyFrame::WriteInitialText()
751{
5d7836c4
JS
752 wxRichTextCtrl& r = *m_richTextCtrl;
753
99404ab0
JS
754 r.SetDefaultStyle(wxRichTextAttr());
755
5d7836c4
JS
756 r.BeginSuppressUndo();
757
cdaed652
VZ
758 r.Freeze();
759
5d7836c4
JS
760 r.BeginParagraphSpacing(0, 20);
761
762 r.BeginAlignment(wxTEXT_ALIGNMENT_CENTRE);
763 r.BeginBold();
764
765 r.BeginFontSize(14);
c3e54dee 766
50f65288 767 wxString lineBreak = (wxChar) 29;
c3e54dee 768
99404ab0 769 r.WriteText(wxString(wxT("Welcome to wxRichTextCtrl, a wxWidgets control")) + lineBreak + wxT("for editing and presenting styled text and images\n"));
5d7836c4 770 r.EndFontSize();
5d7836c4
JS
771
772 r.BeginItalic();
773 r.WriteText(wxT("by Julian Smart"));
774 r.EndItalic();
775
776 r.EndBold();
5d7836c4 777 r.Newline();
42688aea 778
5d7836c4
JS
779 r.WriteImage(wxBitmap(zebra_xpm));
780
5d7836c4
JS
781 r.Newline();
782 r.Newline();
783
99404ab0
JS
784 r.EndAlignment();
785
cdaed652 786 r.BeginAlignment(wxTEXT_ALIGNMENT_LEFT);
24777478
JS
787 wxRichTextAttr imageAttr;
788 imageAttr.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_LEFT);
cdaed652 789 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
790 r.WriteImage(wxBitmap(zebra_xpm), wxBITMAP_TYPE_PNG, imageAttr);
791 imageAttr.GetTextBoxAttr().GetTop().SetValue(200);
792 imageAttr.GetTextBoxAttr().GetTop().SetUnits(wxTEXT_ATTR_UNITS_PIXELS);
793 imageAttr.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_RIGHT);
794 r.WriteImage(wxBitmap(zebra_xpm), wxBITMAP_TYPE_PNG, imageAttr);
5ad9ae3a 795 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
796 r.EndAlignment();
797 r.Newline();
798
5d7836c4 799 r.WriteText(wxT("What can you do with this thing? "));
42688aea 800
5d7836c4
JS
801 r.WriteImage(wxBitmap(smiley_xpm));
802 r.WriteText(wxT(" Well, you can change text "));
803
804 r.BeginTextColour(wxColour(255, 0, 0));
805 r.WriteText(wxT("colour, like this red bit."));
806 r.EndTextColour();
807
3e541562
JS
808 wxRichTextAttr backgroundColourAttr;
809 backgroundColourAttr.SetBackgroundColour(*wxGREEN);
810 backgroundColourAttr.SetTextColour(wxColour(0, 0, 255));
811 r.BeginStyle(backgroundColourAttr);
812 r.WriteText(wxT(" And this blue on green bit."));
813 r.EndStyle();
5d7836c4
JS
814
815 r.WriteText(wxT(" Naturally you can make things "));
816 r.BeginBold();
817 r.WriteText(wxT("bold "));
818 r.EndBold();
819 r.BeginItalic();
820 r.WriteText(wxT("or italic "));
821 r.EndItalic();
822 r.BeginUnderline();
823 r.WriteText(wxT("or underlined."));
824 r.EndUnderline();
825
826 r.BeginFontSize(14);
827 r.WriteText(wxT(" Different font sizes on the same line is allowed, too."));
828 r.EndFontSize();
829
830 r.WriteText(wxT(" Next we'll show an indented paragraph."));
831
5d7836c4
JS
832 r.Newline();
833
99404ab0 834 r.BeginLeftIndent(60);
5d7836c4 835 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
836 r.Newline();
837
99404ab0
JS
838 r.EndLeftIndent();
839
5d7836c4
JS
840 r.WriteText(wxT("Next, we'll show a first-line indent, achieved using BeginLeftIndent(100, -40)."));
841
5d7836c4
JS
842 r.Newline();
843
99404ab0 844 r.BeginLeftIndent(100, -40);
5d7836c4 845
99404ab0 846 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
847 r.Newline();
848
99404ab0 849 r.EndLeftIndent();
5d7836c4 850
99404ab0 851 r.WriteText(wxT("Numbered bullets are possible, again using subindents:"));
5d7836c4
JS
852 r.Newline();
853
99404ab0 854 r.BeginNumberedBullet(1, 100, 60);
082cfe55 855 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 856 r.Newline();
5d7836c4
JS
857 r.EndNumberedBullet();
858
859 r.BeginNumberedBullet(2, 100, 60);
5d7836c4 860 r.WriteText(wxT("This is my second item."));
5d7836c4 861 r.Newline();
99404ab0 862 r.EndNumberedBullet();
5d7836c4
JS
863
864 r.WriteText(wxT("The following paragraph is right-indented:"));
99404ab0 865 r.Newline();
5d7836c4
JS
866
867 r.BeginRightIndent(200);
5d7836c4
JS
868
869 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
870 r.Newline();
871
99404ab0
JS
872 r.EndRightIndent();
873
5d7836c4 874 r.WriteText(wxT("The following paragraph is right-aligned with 1.5 line spacing:"));
99404ab0 875 r.Newline();
5d7836c4
JS
876
877 r.BeginAlignment(wxTEXT_ALIGNMENT_RIGHT);
878 r.BeginLineSpacing(wxTEXT_ATTR_LINE_SPACING_HALF);
5d7836c4 879 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 880 r.Newline();
5d7836c4
JS
881 r.EndLineSpacing();
882 r.EndAlignment();
883
7f0d9d71
JS
884 wxArrayInt tabs;
885 tabs.Add(400);
886 tabs.Add(600);
887 tabs.Add(800);
888 tabs.Add(1000);
24777478 889 wxRichTextAttr attr;
7f0d9d71
JS
890 attr.SetFlags(wxTEXT_ATTR_TABS);
891 attr.SetTabs(tabs);
892 r.SetDefaultStyle(attr);
4753c7ce 893
7f0d9d71 894 r.WriteText(wxT("This line contains tabs:\tFirst tab\tSecond tab\tThird tab"));
5d7836c4 895 r.Newline();
99404ab0 896
5d7836c4 897 r.WriteText(wxT("Other notable features of wxRichTextCtrl include:"));
99404ab0 898 r.Newline();
5d7836c4
JS
899
900 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 901 r.WriteText(wxT("Compatibility with wxTextCtrl API"));
99404ab0 902 r.Newline();
5d7836c4
JS
903 r.EndSymbolBullet();
904
905 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 906 r.WriteText(wxT("Easy stack-based BeginXXX()...EndXXX() style setting in addition to SetStyle()"));
99404ab0 907 r.Newline();
5d7836c4
JS
908 r.EndSymbolBullet();
909
910 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 911 r.WriteText(wxT("XML loading and saving"));
99404ab0 912 r.Newline();
5d7836c4
JS
913 r.EndSymbolBullet();
914
915 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 916 r.WriteText(wxT("Undo/Redo, with batching option and Undo suppressing"));
99404ab0 917 r.Newline();
5d7836c4
JS
918 r.EndSymbolBullet();
919
920 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 921 r.WriteText(wxT("Clipboard copy and paste"));
99404ab0 922 r.Newline();
5d7836c4
JS
923 r.EndSymbolBullet();
924
925 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 926 r.WriteText(wxT("wxRichTextStyleSheet with named character and paragraph styles, and control for applying named styles"));
99404ab0 927 r.Newline();
5d7836c4
JS
928 r.EndSymbolBullet();
929
930 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 931 r.WriteText(wxT("A design that can easily be extended to other content types, ultimately with text boxes, tables, controls, and so on"));
5d7836c4 932 r.Newline();
99404ab0 933 r.EndSymbolBullet();
5d7836c4 934
720cc10a
JS
935 // Make a style suitable for showing a URL
936 wxRichTextAttr urlStyle;
937 urlStyle.SetTextColour(*wxBLUE);
938 urlStyle.SetFontUnderlined(true);
939
940 r.WriteText(wxT("wxRichTextCtrl can also display URLs, such as this one: "));
941 r.BeginStyle(urlStyle);
942 r.BeginURL(wxT("http://www.wxwidgets.org"));
943 r.WriteText(wxT("The wxWidgets Web Site"));
944 r.EndURL();
945 r.EndStyle();
946 r.WriteText(wxT(". Click on the URL to generate an event."));
947
948 r.Newline();
949
99404ab0 950 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
951
952 r.EndParagraphSpacing();
953
cdaed652
VZ
954 r.Thaw();
955
5d7836c4
JS
956 r.EndSuppressUndo();
957}
958
5d7836c4
JS
959// event handlers
960
961void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
962{
963 // true is to force the frame to close
964 Close(true);
965}
966
967void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
968{
969 wxString msg;
9a83f860
VZ
970 msg.Printf( wxT("This is a demo for wxRichTextCtrl, a control for editing styled text.\n(c) Julian Smart, 2005"));
971 wxMessageBox(msg, wxT("About wxRichTextCtrl Sample"), wxOK | wxICON_INFORMATION, this);
5d7836c4
JS
972}
973
974// Forward command events to the current rich text control, if any
975bool MyFrame::ProcessEvent(wxEvent& event)
976{
977 if (event.IsCommandEvent() && !event.IsKindOf(CLASSINFO(wxChildFocusEvent)))
978 {
979 // Problem: we can get infinite recursion because the events
980 // climb back up to this frame, and repeat.
981 // Assume that command events don't cause another command event
982 // to be called, so we can rely on inCommand not being overwritten
983
984 static int s_eventType = 0;
985 static wxWindowID s_id = 0;
986
987 if (s_id != event.GetId() && s_eventType != event.GetEventType())
988 {
989 s_eventType = event.GetEventType();
990 s_id = event.GetId();
9a173d48 991
5d7836c4 992 wxWindow* focusWin = wxFindFocusDescendant(this);
004867db 993 if (focusWin && focusWin->GetEventHandler()->ProcessEvent(event))
5d7836c4
JS
994 {
995 //s_command = NULL;
996 s_eventType = 0;
997 s_id = 0;
9a173d48 998 return true;
5d7836c4
JS
999 }
1000
1001 s_eventType = 0;
1002 s_id = 0;
1003 }
1004 else
1005 {
9a173d48 1006 return false;
5d7836c4
JS
1007 }
1008 }
1009
1010 return wxFrame::ProcessEvent(event);
1011}
1012
011b3dcb 1013void MyFrame::OnOpen(wxCommandEvent& WXUNUSED(event))
5d7836c4 1014{
9a173d48
WS
1015 wxString path;
1016 wxString filename;
1e967276
JS
1017 wxArrayInt fileTypes;
1018
1019 wxString filter = wxRichTextBuffer::GetExtWildcard(false, false, & fileTypes);
9a173d48 1020 if (!filter.empty())
5d7836c4
JS
1021 filter += wxT("|");
1022 filter += wxT("All files (*.*)|*.*");
1023
5d7836c4
JS
1024 wxFileDialog dialog(this,
1025 _("Choose a filename"),
1026 path,
1027 filename,
1028 filter,
ff3e84ff 1029 wxFD_OPEN);
5d7836c4
JS
1030
1031 if (dialog.ShowModal() == wxID_OK)
1032 {
1033 wxString path = dialog.GetPath();
9a173d48
WS
1034
1035 if (!path.empty())
5d7836c4 1036 {
1e967276 1037 int filterIndex = dialog.GetFilterIndex();
dbf38e88
WS
1038 int fileType = (filterIndex < (int) fileTypes.GetCount())
1039 ? fileTypes[filterIndex]
1040 : wxRICHTEXT_TYPE_TEXT;
1e967276 1041 m_richTextCtrl->LoadFile(path, fileType);
5d7836c4
JS
1042 }
1043 }
1044}
1045
1046void MyFrame::OnSave(wxCommandEvent& event)
1047{
9a173d48 1048 if (m_richTextCtrl->GetFilename().empty())
5d7836c4
JS
1049 {
1050 OnSaveAs(event);
1051 return;
1052 }
1053 m_richTextCtrl->SaveFile();
1054}
1055
011b3dcb 1056void MyFrame::OnSaveAs(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1057{
1058 wxString filter = wxRichTextBuffer::GetExtWildcard(false, true);
9a173d48
WS
1059 wxString path;
1060 wxString filename;
5d7836c4
JS
1061
1062 wxFileDialog dialog(this,
1063 _("Choose a filename"),
1064 path,
1065 filename,
1066 filter,
ff3e84ff 1067 wxFD_SAVE);
5d7836c4
JS
1068
1069 if (dialog.ShowModal() == wxID_OK)
1070 {
1071 wxString path = dialog.GetPath();
9a173d48
WS
1072
1073 if (!path.empty())
5d7836c4 1074 {
bec80f4f
JS
1075 wxBusyCursor busy;
1076 wxStopWatch stopwatch;
1077
5d7836c4 1078 m_richTextCtrl->SaveFile(path);
bec80f4f
JS
1079
1080 long t = stopwatch.Time();
1081 wxLogDebug(wxT("Saving took %ldms"), t);
1082 wxMessageBox(wxString::Format(wxT("Saving took %ldms"), t));
5d7836c4
JS
1083 }
1084 }
1085}
1086
011b3dcb 1087void MyFrame::OnBold(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1088{
1089 m_richTextCtrl->ApplyBoldToSelection();
1090}
1091
011b3dcb 1092void MyFrame::OnItalic(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1093{
1094 m_richTextCtrl->ApplyItalicToSelection();
1095}
1096
011b3dcb 1097void MyFrame::OnUnderline(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1098{
1099 m_richTextCtrl->ApplyUnderlineToSelection();
1100}
1101
1102
1103void MyFrame::OnUpdateBold(wxUpdateUIEvent& event)
1104{
1105 event.Check(m_richTextCtrl->IsSelectionBold());
1106}
1107
1108void MyFrame::OnUpdateItalic(wxUpdateUIEvent& event)
1109{
1110 event.Check(m_richTextCtrl->IsSelectionItalics());
1111}
1112
1113void MyFrame::OnUpdateUnderline(wxUpdateUIEvent& event)
1114{
1115 event.Check(m_richTextCtrl->IsSelectionUnderlined());
1116}
1117
011b3dcb 1118void MyFrame::OnAlignLeft(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1119{
1120 m_richTextCtrl->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_LEFT);
1121}
1122
011b3dcb 1123void MyFrame::OnAlignCentre(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1124{
1125 m_richTextCtrl->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_CENTRE);
1126}
1127
011b3dcb 1128void MyFrame::OnAlignRight(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1129{
1130 m_richTextCtrl->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_RIGHT);
1131}
1132
1133void MyFrame::OnUpdateAlignLeft(wxUpdateUIEvent& event)
1134{
1135 event.Check(m_richTextCtrl->IsSelectionAligned(wxTEXT_ALIGNMENT_LEFT));
1136}
1137
1138void MyFrame::OnUpdateAlignCentre(wxUpdateUIEvent& event)
1139{
1140 event.Check(m_richTextCtrl->IsSelectionAligned(wxTEXT_ALIGNMENT_CENTRE));
1141}
1142
1143void MyFrame::OnUpdateAlignRight(wxUpdateUIEvent& event)
1144{
1145 event.Check(m_richTextCtrl->IsSelectionAligned(wxTEXT_ALIGNMENT_RIGHT));
1146}
1147
011b3dcb 1148void MyFrame::OnFont(wxCommandEvent& WXUNUSED(event))
5d7836c4 1149{
8c9c49a1
JS
1150 wxRichTextRange range;
1151 if (m_richTextCtrl->HasSelection())
1152 range = m_richTextCtrl->GetSelectionRange();
1153 else
1154 range = wxRichTextRange(0, m_richTextCtrl->GetLastPosition()+1);
1155
1156 int pages = wxRICHTEXT_FORMAT_FONT;
1157
1158 wxRichTextFormattingDialog formatDlg(pages, this);
1159 formatDlg.GetStyle(m_richTextCtrl, range);
1160
1161 if (formatDlg.ShowModal() == wxID_OK)
1162 {
42688aea 1163 formatDlg.ApplyStyle(m_richTextCtrl, range, wxRICHTEXT_SETSTYLE_WITH_UNDO|wxRICHTEXT_SETSTYLE_OPTIMIZE|wxRICHTEXT_SETSTYLE_CHARACTERS_ONLY);
8c9c49a1
JS
1164 }
1165
1166 // Old method using wxFontDialog
1167#if 0
5d7836c4
JS
1168 if (!m_richTextCtrl->HasSelection())
1169 return;
1170
1171 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1172 wxFontData fontData;
1173
24777478 1174 wxRichTextAttr attr;
5d7836c4
JS
1175 attr.SetFlags(wxTEXT_ATTR_FONT);
1176
1177 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1178 fontData.SetInitialFont(attr.GetFont());
1179
1180 wxFontDialog dialog(this, fontData);
1181 if (dialog.ShowModal() == wxID_OK)
1182 {
1183 fontData = dialog.GetFontData();
1184 attr.SetFlags(wxTEXT_ATTR_FONT);
1185 attr.SetFont(fontData.GetChosenFont());
1186 if (attr.GetFont().Ok())
1187 {
1188 m_richTextCtrl->SetStyle(range, attr);
1189 }
1190 }
8c9c49a1
JS
1191#endif
1192}
1193
cdaed652
VZ
1194void MyFrame::OnImage(wxCommandEvent& WXUNUSED(event))
1195{
1196 wxRichTextRange range;
1197 wxASSERT(m_richTextCtrl->HasSelection());
1198
1199 range = m_richTextCtrl->GetSelectionRange();
1200 wxASSERT(range.ToInternal().GetLength() == 1);
1201
1202 wxRichTextImage* image = wxDynamicCast(m_richTextCtrl->GetBuffer().GetLeafObjectAtPosition(range.GetStart()), wxRichTextImage);
1203 if (image)
1204 {
1205 wxRichTextImageDialog imageDlg(this);
1206 imageDlg.SetImageObject(image, &m_richTextCtrl->GetBuffer());
1207
1208 if (imageDlg.ShowModal() == wxID_OK)
1209 {
1210 image = imageDlg.ApplyImageAttr();
1211 }
1212 }
1213}
1214
8c9c49a1
JS
1215void MyFrame::OnParagraph(wxCommandEvent& WXUNUSED(event))
1216{
1217 wxRichTextRange range;
1218 if (m_richTextCtrl->HasSelection())
1219 range = m_richTextCtrl->GetSelectionRange();
1220 else
1221 range = wxRichTextRange(0, m_richTextCtrl->GetLastPosition()+1);
1222
1223 int pages = wxRICHTEXT_FORMAT_INDENTS_SPACING|wxRICHTEXT_FORMAT_TABS|wxRICHTEXT_FORMAT_BULLETS;
1224
1225 wxRichTextFormattingDialog formatDlg(pages, this);
1226 formatDlg.GetStyle(m_richTextCtrl, range);
1227
1228 if (formatDlg.ShowModal() == wxID_OK)
1229 {
1230 formatDlg.ApplyStyle(m_richTextCtrl, range);
1231 }
1232}
1233
1234void MyFrame::OnFormat(wxCommandEvent& WXUNUSED(event))
1235{
1236 wxRichTextRange range;
1237 if (m_richTextCtrl->HasSelection())
1238 range = m_richTextCtrl->GetSelectionRange();
1239 else
1240 range = wxRichTextRange(0, m_richTextCtrl->GetLastPosition()+1);
1241
1242 int pages = wxRICHTEXT_FORMAT_FONT|wxRICHTEXT_FORMAT_INDENTS_SPACING|wxRICHTEXT_FORMAT_TABS|wxRICHTEXT_FORMAT_BULLETS;
1243
1244 wxRichTextFormattingDialog formatDlg(pages, this);
1245 formatDlg.GetStyle(m_richTextCtrl, range);
1246
1247 if (formatDlg.ShowModal() == wxID_OK)
1248 {
1249 formatDlg.ApplyStyle(m_richTextCtrl, range);
1250 }
1251}
1252
1253void MyFrame::OnUpdateFormat(wxUpdateUIEvent& event)
1254{
1255 event.Enable(m_richTextCtrl->HasSelection());
5d7836c4
JS
1256}
1257
cdaed652
VZ
1258void MyFrame::OnUpdateImage(wxUpdateUIEvent& event)
1259{
1260 wxRichTextRange range;
1261 wxRichTextObject *obj;
1262
1263 range = m_richTextCtrl->GetSelectionRange();
1264 if (range.ToInternal().GetLength() == 1)
1265 {
1266 obj = m_richTextCtrl->GetBuffer().GetLeafObjectAtPosition(range.GetStart());
1267 if (obj && obj->IsKindOf(CLASSINFO(wxRichTextImage)))
1268 {
1269 event.Enable(true);
1270 return;
1271 }
1272 }
1273
1274 event.Enable(false);
1275}
1276
011b3dcb 1277void MyFrame::OnIndentMore(wxCommandEvent& WXUNUSED(event))
5d7836c4 1278{
44cc96a8 1279 wxRichTextAttr attr;
5d7836c4
JS
1280 attr.SetFlags(wxTEXT_ATTR_LEFT_INDENT);
1281
1282 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1283 {
1284 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1285 if (m_richTextCtrl->HasSelection())
1286 range = m_richTextCtrl->GetSelectionRange();
1287
5d7836c4
JS
1288 attr.SetLeftIndent(attr.GetLeftIndent() + 100);
1289
1290 attr.SetFlags(wxTEXT_ATTR_LEFT_INDENT);
1291 m_richTextCtrl->SetStyle(range, attr);
1292 }
1293}
1294
011b3dcb 1295void MyFrame::OnIndentLess(wxCommandEvent& WXUNUSED(event))
5d7836c4 1296{
44cc96a8 1297 wxRichTextAttr attr;
5d7836c4
JS
1298 attr.SetFlags(wxTEXT_ATTR_LEFT_INDENT);
1299
1300 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1301 {
1302 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1303 if (m_richTextCtrl->HasSelection())
1304 range = m_richTextCtrl->GetSelectionRange();
1305
c3e54dee 1306 if (attr.GetLeftIndent() > 0)
5d7836c4 1307 {
c3e54dee 1308 attr.SetLeftIndent(wxMax(0, attr.GetLeftIndent() - 100));
9a173d48 1309
5d7836c4
JS
1310 m_richTextCtrl->SetStyle(range, attr);
1311 }
1312 }
1313}
1314
011b3dcb 1315void MyFrame::OnLineSpacingHalf(wxCommandEvent& WXUNUSED(event))
5d7836c4 1316{
44cc96a8 1317 wxRichTextAttr attr;
5d7836c4
JS
1318 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1319
1320 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1321 {
1322 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1323 if (m_richTextCtrl->HasSelection())
1324 range = m_richTextCtrl->GetSelectionRange();
1325
5d7836c4
JS
1326 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1327 attr.SetLineSpacing(15);
9a173d48 1328
5d7836c4
JS
1329 m_richTextCtrl->SetStyle(range, attr);
1330 }
1331}
1332
011b3dcb 1333void MyFrame::OnLineSpacingDouble(wxCommandEvent& WXUNUSED(event))
5d7836c4 1334{
44cc96a8 1335 wxRichTextAttr attr;
5d7836c4
JS
1336 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1337
1338 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1339 {
1340 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1341 if (m_richTextCtrl->HasSelection())
1342 range = m_richTextCtrl->GetSelectionRange();
1343
5d7836c4
JS
1344 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1345 attr.SetLineSpacing(20);
9a173d48 1346
5d7836c4
JS
1347 m_richTextCtrl->SetStyle(range, attr);
1348 }
1349}
1350
011b3dcb 1351void MyFrame::OnLineSpacingSingle(wxCommandEvent& WXUNUSED(event))
5d7836c4 1352{
44cc96a8 1353 wxRichTextAttr attr;
5d7836c4
JS
1354 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1355
1356 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1357 {
1358 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1359 if (m_richTextCtrl->HasSelection())
1360 range = m_richTextCtrl->GetSelectionRange();
1361
5d7836c4
JS
1362 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1363 attr.SetLineSpacing(0); // Can also use 10
9a173d48 1364
5d7836c4
JS
1365 m_richTextCtrl->SetStyle(range, attr);
1366 }
1367}
1368
011b3dcb 1369void MyFrame::OnParagraphSpacingMore(wxCommandEvent& WXUNUSED(event))
5d7836c4 1370{
44cc96a8 1371 wxRichTextAttr attr;
5d7836c4
JS
1372 attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER);
1373
1374 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1375 {
1376 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1377 if (m_richTextCtrl->HasSelection())
1378 range = m_richTextCtrl->GetSelectionRange();
1379
5d7836c4
JS
1380 attr.SetParagraphSpacingAfter(attr.GetParagraphSpacingAfter() + 20);
1381
1382 attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER);
1383 m_richTextCtrl->SetStyle(range, attr);
1384 }
1385}
1386
011b3dcb 1387void MyFrame::OnParagraphSpacingLess(wxCommandEvent& WXUNUSED(event))
5d7836c4 1388{
44cc96a8 1389 wxRichTextAttr attr;
5d7836c4
JS
1390 attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER);
1391
1392 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1393 {
1394 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1395 if (m_richTextCtrl->HasSelection())
1396 range = m_richTextCtrl->GetSelectionRange();
1397
1398 if (attr.GetParagraphSpacingAfter() >= 20)
1399 {
5d7836c4 1400 attr.SetParagraphSpacingAfter(attr.GetParagraphSpacingAfter() - 20);
9a173d48 1401
5d7836c4
JS
1402 attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER);
1403 m_richTextCtrl->SetStyle(range, attr);
1404 }
1405 }
1406}
1407
99404ab0
JS
1408void MyFrame::OnReload(wxCommandEvent& WXUNUSED(event))
1409{
1410 m_richTextCtrl->Clear();
1411 WriteInitialText();
1412}
1413
011b3dcb 1414void MyFrame::OnViewHTML(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1415{
1416 wxDialog dialog(this, wxID_ANY, _("HTML"), wxDefaultPosition, wxSize(500, 400), wxDEFAULT_DIALOG_STYLE);
1417
1418 wxBoxSizer* boxSizer = new wxBoxSizer(wxVERTICAL);
1419 dialog.SetSizer(boxSizer);
1420
1421 wxHtmlWindow* win = new wxHtmlWindow(& dialog, wxID_ANY, wxDefaultPosition, wxSize(500, 400), wxSUNKEN_BORDER);
1422 boxSizer->Add(win, 1, wxALL, 5);
1423
1424 wxButton* cancelButton = new wxButton(& dialog, wxID_CANCEL, wxT("&Close"));
1425 boxSizer->Add(cancelButton, 0, wxALL|wxCENTRE, 5);
1426
1427 wxString text;
1428 wxStringOutputStream strStream(& text);
1429
1430 wxRichTextHTMLHandler htmlHandler;
720cc10a 1431 htmlHandler.SetFlags(wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_MEMORY);
c3e54dee 1432
50f65288
WS
1433 wxArrayInt fontSizeMapping;
1434 fontSizeMapping.Add(7);
1435 fontSizeMapping.Add(9);
1436 fontSizeMapping.Add(11);
1437 fontSizeMapping.Add(12);
1438 fontSizeMapping.Add(14);
1439 fontSizeMapping.Add(22);
1440 fontSizeMapping.Add(100);
c3e54dee 1441
50f65288 1442 htmlHandler.SetFontSizeMapping(fontSizeMapping);
720cc10a 1443
5d7836c4
JS
1444 if (htmlHandler.SaveFile(& m_richTextCtrl->GetBuffer(), strStream))
1445 {
1446 win->SetPage(text);
1447 }
1448
1449 boxSizer->Fit(& dialog);
1450
1451 dialog.ShowModal();
720cc10a
JS
1452
1453 // Now delete the temporary in-memory images
1454 htmlHandler.DeleteTemporaryImages();
5d7836c4 1455}
fe5aa22c
JS
1456
1457// Demonstrates how you can change the style sheets and have the changes
1458// reflected in the control content without wiping out character formatting.
1459
1460void MyFrame::OnSwitchStyleSheets(wxCommandEvent& WXUNUSED(event))
1461{
1462 static wxRichTextStyleSheet* gs_AlternateStyleSheet = NULL;
1463
e4723634 1464 wxRichTextStyleListCtrl *styleList = (wxRichTextStyleListCtrl*) FindWindow(ID_RICHTEXT_STYLE_LIST);
fe5aa22c
JS
1465 wxRichTextStyleComboCtrl* styleCombo = (wxRichTextStyleComboCtrl*) FindWindow(ID_RICHTEXT_STYLE_COMBO);
1466
8881d9f0 1467 wxRichTextStyleSheet* sheet = m_richTextCtrl->GetStyleSheet();
fe5aa22c
JS
1468
1469 // One-time creation of an alternate style sheet
1470 if (!gs_AlternateStyleSheet)
1471 {
1472 gs_AlternateStyleSheet = new wxRichTextStyleSheet(*sheet);
1473
1474 // Make some modifications
1475 for (int i = 0; i < (int) gs_AlternateStyleSheet->GetParagraphStyleCount(); i++)
1476 {
1477 wxRichTextParagraphStyleDefinition* def = gs_AlternateStyleSheet->GetParagraphStyle(i);
1478
1479 if (def->GetStyle().HasTextColour())
1480 def->GetStyle().SetTextColour(*wxBLUE);
1481
1482 if (def->GetStyle().HasAlignment())
1483 {
1484 if (def->GetStyle().GetAlignment() == wxTEXT_ALIGNMENT_CENTRE)
1485 def->GetStyle().SetAlignment(wxTEXT_ALIGNMENT_RIGHT);
1486 else if (def->GetStyle().GetAlignment() == wxTEXT_ALIGNMENT_LEFT)
1487 def->GetStyle().SetAlignment(wxTEXT_ALIGNMENT_CENTRE);
1488 }
1489 if (def->GetStyle().HasLeftIndent())
1490 {
1491 def->GetStyle().SetLeftIndent(def->GetStyle().GetLeftIndent() * 2);
1492 }
1493 }
1494 }
1495
1496 // Switch sheets
1497 wxRichTextStyleSheet* tmp = gs_AlternateStyleSheet;
1498 gs_AlternateStyleSheet = sheet;
1499 sheet = tmp;
1500
8881d9f0
JS
1501 m_richTextCtrl->SetStyleSheet(sheet);
1502 m_richTextCtrl->ApplyStyleSheet(sheet); // Makes the control reflect the new style definitions
fe5aa22c
JS
1503
1504 styleList->SetStyleSheet(sheet);
1505 styleList->UpdateStyles();
1506
1507 styleCombo->SetStyleSheet(sheet);
1508 styleCombo->UpdateStyles();
1509}
8c9c49a1 1510
e4723634
JS
1511void MyFrame::OnManageStyles(wxCommandEvent& WXUNUSED(event))
1512{
8881d9f0 1513 wxRichTextStyleSheet* sheet = m_richTextCtrl->GetStyleSheet();
e4723634
JS
1514
1515 int flags = wxRICHTEXT_ORGANISER_CREATE_STYLES|wxRICHTEXT_ORGANISER_EDIT_STYLES;
1516
1517 wxRichTextStyleOrganiserDialog dlg(flags, sheet, NULL, this, wxID_ANY, _("Style Manager"));
1518 dlg.ShowModal();
1519}
1520
8c9c49a1
JS
1521void MyFrame::OnInsertSymbol(wxCommandEvent& WXUNUSED(event))
1522{
44cc96a8 1523 wxRichTextAttr attr;
8c9c49a1 1524 attr.SetFlags(wxTEXT_ATTR_FONT);
8881d9f0 1525 m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr);
8c9c49a1
JS
1526
1527 wxString currentFontName;
1528 if (attr.HasFont() && attr.GetFont().Ok())
1529 currentFontName = attr.GetFont().GetFaceName();
1530
1531 // Don't set the initial font in the dialog (so the user is choosing
1532 // 'normal text', i.e. the current font) but do tell the dialog
1533 // what 'normal text' is.
1534
1535 wxSymbolPickerDialog dlg(wxT("*"), wxEmptyString, currentFontName, this);
1536
1537 if (dlg.ShowModal() == wxID_OK)
1538 {
1539 if (dlg.HasSelection())
1540 {
8881d9f0 1541 long insertionPoint = m_richTextCtrl->GetInsertionPoint();
8c9c49a1 1542
8881d9f0 1543 m_richTextCtrl->WriteText(dlg.GetSymbol());
8c9c49a1
JS
1544
1545 if (!dlg.UseNormalFont())
1546 {
1547 wxFont font(attr.GetFont());
23c386ba 1548 font.SetFaceName(dlg.GetFontName());
8c9c49a1 1549 attr.SetFont(font);
8881d9f0 1550 m_richTextCtrl->SetStyle(insertionPoint, insertionPoint+1, attr);
8c9c49a1
JS
1551 }
1552 }
1553 }
1554}
082cfe55
JS
1555
1556void MyFrame::OnNumberList(wxCommandEvent& WXUNUSED(event))
1557{
8881d9f0 1558 if (m_richTextCtrl->HasSelection())
082cfe55 1559 {
8881d9f0
JS
1560 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1561 m_richTextCtrl->SetListStyle(range, wxT("Numbered List 1"), wxRICHTEXT_SETSTYLE_WITH_UNDO|wxRICHTEXT_SETSTYLE_RENUMBER);
082cfe55
JS
1562 }
1563}
1564
e4723634
JS
1565void MyFrame::OnBulletsAndNumbering(wxCommandEvent& WXUNUSED(event))
1566{
8881d9f0 1567 wxRichTextStyleSheet* sheet = m_richTextCtrl->GetStyleSheet();
e4723634
JS
1568
1569 int flags = wxRICHTEXT_ORGANISER_BROWSE_NUMBERING;
1570
8881d9f0 1571 wxRichTextStyleOrganiserDialog dlg(flags, sheet, m_richTextCtrl, this, wxID_ANY, _("Bullets and Numbering"));
e4723634
JS
1572 if (dlg.ShowModal() == wxID_OK)
1573 {
1574 if (dlg.GetSelectedStyleDefinition())
1575 dlg.ApplyStyle();
1576 }
1577}
1578
082cfe55
JS
1579void MyFrame::OnItemizeList(wxCommandEvent& WXUNUSED(event))
1580{
8881d9f0 1581 if (m_richTextCtrl->HasSelection())
082cfe55 1582 {
8881d9f0
JS
1583 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1584 m_richTextCtrl->SetListStyle(range, wxT("Bullet List 1"));
082cfe55
JS
1585 }
1586}
1587
1588void MyFrame::OnRenumberList(wxCommandEvent& WXUNUSED(event))
1589{
8881d9f0 1590 if (m_richTextCtrl->HasSelection())
082cfe55 1591 {
8881d9f0
JS
1592 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1593 m_richTextCtrl->NumberList(range, NULL, wxRICHTEXT_SETSTYLE_WITH_UNDO|wxRICHTEXT_SETSTYLE_RENUMBER);
082cfe55
JS
1594 }
1595}
1596
1597void MyFrame::OnPromoteList(wxCommandEvent& WXUNUSED(event))
1598{
8881d9f0 1599 if (m_richTextCtrl->HasSelection())
082cfe55 1600 {
8881d9f0
JS
1601 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1602 m_richTextCtrl->PromoteList(1, range, NULL);
082cfe55
JS
1603 }
1604}
1605
1606void MyFrame::OnDemoteList(wxCommandEvent& WXUNUSED(event))
1607{
8881d9f0 1608 if (m_richTextCtrl->HasSelection())
082cfe55 1609 {
8881d9f0
JS
1610 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1611 m_richTextCtrl->PromoteList(-1, range, NULL);
082cfe55
JS
1612 }
1613}
1614
1615void MyFrame::OnClearList(wxCommandEvent& WXUNUSED(event))
1616{
8881d9f0 1617 if (m_richTextCtrl->HasSelection())
082cfe55 1618 {
8881d9f0
JS
1619 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1620 m_richTextCtrl->ClearListStyle(range);
082cfe55
JS
1621 }
1622}
1623
720cc10a
JS
1624void MyFrame::OnInsertURL(wxCommandEvent& WXUNUSED(event))
1625{
1626 wxString url = wxGetTextFromUser(_("URL:"), _("Insert URL"));
1627 if (!url.IsEmpty())
1628 {
720cc10a
JS
1629 // Make a style suitable for showing a URL
1630 wxRichTextAttr urlStyle;
1631 urlStyle.SetTextColour(*wxBLUE);
1632 urlStyle.SetFontUnderlined(true);
c3e54dee 1633
8881d9f0
JS
1634 m_richTextCtrl->BeginStyle(urlStyle);
1635 m_richTextCtrl->BeginURL(url);
1636 m_richTextCtrl->WriteText(url);
1637 m_richTextCtrl->EndURL();
1638 m_richTextCtrl->EndStyle();
720cc10a
JS
1639 }
1640}
1641
cdaed652
VZ
1642void MyFrame::OnInsertImage(wxCommandEvent& WXUNUSED(event))
1643{
1644 wxFileDialog dialog(this, _("Choose an image"), "", "", "BMP and GIF files (*.bmp;*.gif)|*.bmp;*.gif|PNG files (*.png)|*.png");
1645 if (dialog.ShowModal() == wxID_OK)
1646 {
1647 wxString path = dialog.GetPath();
1648 m_richTextCtrl->WriteImage(path, wxBITMAP_TYPE_ANY);
1649 }
1650}
1651
720cc10a
JS
1652void MyFrame::OnURL(wxTextUrlEvent& event)
1653{
1654 wxMessageBox(event.GetString());
1655}
1656
1657// Veto style sheet replace events when loading from XML, since we want
1658// to keep the original style sheet.
1659void MyFrame::OnStyleSheetReplacing(wxRichTextEvent& event)
1660{
1661 event.Veto();
1662}
8881d9f0
JS
1663
1664void MyFrame::OnPrint(wxCommandEvent& WXUNUSED(event))
1665{
1666 wxGetApp().GetPrinting()->PrintBuffer(m_richTextCtrl->GetBuffer());
1667}
1668
1669void MyFrame::OnPreview(wxCommandEvent& WXUNUSED(event))
1670{
1671 wxGetApp().GetPrinting()->PreviewBuffer(m_richTextCtrl->GetBuffer());
1672}
1673
1674void MyFrame::OnPageSetup(wxCommandEvent& WXUNUSED(event))
1675{
24777478
JS
1676 wxDialog dialog(this, wxID_ANY, wxT("Testing"), wxPoint(10, 10), wxSize(400, 300), wxDEFAULT_DIALOG_STYLE);
1677
1678 wxNotebook* nb = new wxNotebook(& dialog, wxID_ANY, wxPoint(5, 5), wxSize(300, 250));
1679 wxPanel* panel = new wxPanel(nb, wxID_ANY, wxDefaultPosition, wxDefaultSize);
1680 wxPanel* panel2 = new wxPanel(nb, wxID_ANY, wxDefaultPosition, wxDefaultSize);
1681
d275b15d 1682 new wxRichTextCtrl(panel, wxID_ANY, wxEmptyString, wxPoint(5, 5), wxSize(200, 150), wxVSCROLL|wxTE_READONLY);
24777478
JS
1683 nb->AddPage(panel, wxT("Page 1"));
1684
d275b15d 1685 new wxRichTextCtrl(panel2, wxID_ANY, wxEmptyString, wxPoint(5, 5), wxSize(200, 150), wxVSCROLL|wxTE_READONLY);
24777478
JS
1686 nb->AddPage(panel2, wxT("Page 2"));
1687
d275b15d 1688 new wxButton(& dialog, wxID_OK, wxT("OK"), wxPoint(5, 180));
24777478
JS
1689
1690 dialog.ShowModal();
1691
1692// wxGetApp().GetPrinting()->PageSetup();
8881d9f0 1693}