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