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