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