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