]> git.saurik.com Git - wxWidgets.git/blame - samples/richtext/richtext.cpp
reuse operator bool() check in compatibility_iterator::IndexOf() instead of rewriting it
[wxWidgets.git] / samples / richtext / richtext.cpp
CommitLineData
5d7836c4 1/////////////////////////////////////////////////////////////////////////////
dbf38e88 2// Name: samples/richtext/richtext.cpp
5d7836c4
JS
3// Purpose: wxWidgets rich text editor sample
4// Author: Julian Smart
5// Modified by:
6// Created: 2005-10-02
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx/wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27// for all others, include the necessary headers (this file is usually all you
28// need because it includes almost all "standard" wxWidgets headers)
29#ifndef WX_PRECOMP
30 #include "wx/wx.h"
31#endif
32
33#include "wx/fontdlg.h"
34#include "wx/splitter.h"
35#include "wx/sstream.h"
36#include "wx/html/htmlwin.h"
37
38#include "bitmaps/sample.xpm"
39#include "bitmaps/smiley.xpm"
40// #include "bitmaps/idea.xpm"
41#include "bitmaps/zebra.xpm"
42
43#include "bitmaps/open.xpm"
44#include "bitmaps/save.xpm"
45#include "bitmaps/copy.xpm"
46#include "bitmaps/cut.xpm"
47#include "bitmaps/paste.xpm"
48#include "bitmaps/undo.xpm"
49#include "bitmaps/redo.xpm"
50#include "bitmaps/bold.xpm"
51#include "bitmaps/italic.xpm"
52#include "bitmaps/underline.xpm"
53
54#include "bitmaps/alignleft.xpm"
55#include "bitmaps/alignright.xpm"
56#include "bitmaps/centre.xpm"
57#include "bitmaps/font.xpm"
58#include "bitmaps/indentless.xpm"
59#include "bitmaps/indentmore.xpm"
60
011b3dcb
JS
61#include "wx/richtext/richtextctrl.h"
62#include "wx/richtext/richtextstyles.h"
63#include "wx/richtext/richtextxml.h"
b71e9aa4 64#include "wx/richtext/richtexthtml.h"
5d7836c4
JS
65
66// ----------------------------------------------------------------------------
67// resources
68// ----------------------------------------------------------------------------
69
70// ----------------------------------------------------------------------------
71// private classes
72// ----------------------------------------------------------------------------
73
74// Define a new application type, each program should derive a class from wxApp
75class MyApp : public wxApp
76{
77public:
78 // override base class virtuals
79 // ----------------------------
80
81 // this one is called on application startup and is a good place for the app
82 // initialization (doing it here and not in the ctor allows to have an error
83 // return: if OnInit() returns false, the application terminates)
84 virtual bool OnInit();
85 virtual int OnExit();
86
87 void CreateStyles();
88
89 wxRichTextStyleSheet* GetStyleSheet() const { return m_styleSheet; }
90
91 wxRichTextStyleSheet* m_styleSheet;
92};
93
94// Define a new frame type: this is going to be our main frame
95class MyFrame : public wxFrame
96{
97public:
98 // ctor(s)
99 MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos = wxDefaultPosition,
100 const wxSize& size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE);
101
102 // event handlers (these functions should _not_ be virtual)
103 void OnQuit(wxCommandEvent& event);
104 void OnAbout(wxCommandEvent& event);
105
106 void OnOpen(wxCommandEvent& event);
107 void OnSave(wxCommandEvent& event);
108 void OnSaveAs(wxCommandEvent& event);
109
110 void OnBold(wxCommandEvent& event);
111 void OnItalic(wxCommandEvent& event);
112 void OnUnderline(wxCommandEvent& event);
113
114 void OnUpdateBold(wxUpdateUIEvent& event);
115 void OnUpdateItalic(wxUpdateUIEvent& event);
116 void OnUpdateUnderline(wxUpdateUIEvent& event);
117
118 void OnAlignLeft(wxCommandEvent& event);
119 void OnAlignCentre(wxCommandEvent& event);
120 void OnAlignRight(wxCommandEvent& event);
121
122 void OnUpdateAlignLeft(wxUpdateUIEvent& event);
123 void OnUpdateAlignCentre(wxUpdateUIEvent& event);
124 void OnUpdateAlignRight(wxUpdateUIEvent& event);
125
126 void OnFont(wxCommandEvent& event);
127 void OnIndentMore(wxCommandEvent& event);
128 void OnIndentLess(wxCommandEvent& event);
129
130 void OnLineSpacingHalf(wxCommandEvent& event);
131 void OnLineSpacingDouble(wxCommandEvent& event);
132 void OnLineSpacingSingle(wxCommandEvent& event);
133
134 void OnParagraphSpacingMore(wxCommandEvent& event);
135 void OnParagraphSpacingLess(wxCommandEvent& event);
136
137 void OnViewHTML(wxCommandEvent& event);
138
139 // Forward command events to the current rich text control, if any
140 bool ProcessEvent(wxEvent& event);
141
142private:
143 // any class wishing to process wxWidgets events must use this macro
144 DECLARE_EVENT_TABLE()
145
146 wxRichTextCtrl* m_richTextCtrl;
147};
148
149// ----------------------------------------------------------------------------
150// constants
151// ----------------------------------------------------------------------------
152
153// IDs for the controls and the menu commands
154enum
155{
156 // menu items
157 ID_Quit = wxID_EXIT,
158 ID_About = wxID_ABOUT,
159
160 ID_FORMAT_BOLD = 100,
161 ID_FORMAT_ITALIC,
162 ID_FORMAT_UNDERLINE,
163 ID_FORMAT_FONT,
164
165 ID_FORMAT_ALIGN_LEFT,
166 ID_FORMAT_ALIGN_CENTRE,
167 ID_FORMAT_ALIGN_RIGHT,
168
169 ID_FORMAT_INDENT_MORE,
170 ID_FORMAT_INDENT_LESS,
171
172 ID_FORMAT_PARAGRAPH_SPACING_MORE,
173 ID_FORMAT_PARAGRAPH_SPACING_LESS,
174
175 ID_FORMAT_LINE_SPACING_HALF,
176 ID_FORMAT_LINE_SPACING_DOUBLE,
177 ID_FORMAT_LINE_SPACING_SINGLE,
178
179 ID_VIEW_HTML
180};
181
182// ----------------------------------------------------------------------------
183// event tables and other macros for wxWidgets
184// ----------------------------------------------------------------------------
185
186// the event tables connect the wxWidgets events with the functions (event
187// handlers) which process them. It can be also done at run-time, but for the
188// simple menu events like this the static method is much simpler.
189BEGIN_EVENT_TABLE(MyFrame, wxFrame)
190 EVT_MENU(ID_Quit, MyFrame::OnQuit)
191 EVT_MENU(ID_About, MyFrame::OnAbout)
192
193 EVT_MENU(wxID_OPEN, MyFrame::OnOpen)
194 EVT_MENU(wxID_SAVE, MyFrame::OnSave)
195 EVT_MENU(wxID_SAVEAS, MyFrame::OnSaveAs)
196
197 EVT_MENU(ID_FORMAT_BOLD, MyFrame::OnBold)
198 EVT_MENU(ID_FORMAT_ITALIC, MyFrame::OnItalic)
199 EVT_MENU(ID_FORMAT_UNDERLINE, MyFrame::OnUnderline)
200
201 EVT_UPDATE_UI(ID_FORMAT_BOLD, MyFrame::OnUpdateBold)
202 EVT_UPDATE_UI(ID_FORMAT_ITALIC, MyFrame::OnUpdateItalic)
203 EVT_UPDATE_UI(ID_FORMAT_UNDERLINE, MyFrame::OnUpdateUnderline)
204
205 EVT_MENU(ID_FORMAT_ALIGN_LEFT, MyFrame::OnAlignLeft)
206 EVT_MENU(ID_FORMAT_ALIGN_CENTRE, MyFrame::OnAlignCentre)
207 EVT_MENU(ID_FORMAT_ALIGN_RIGHT, MyFrame::OnAlignRight)
208
209 EVT_UPDATE_UI(ID_FORMAT_ALIGN_LEFT, MyFrame::OnUpdateAlignLeft)
210 EVT_UPDATE_UI(ID_FORMAT_ALIGN_CENTRE, MyFrame::OnUpdateAlignCentre)
211 EVT_UPDATE_UI(ID_FORMAT_ALIGN_RIGHT, MyFrame::OnUpdateAlignRight)
212
213 EVT_MENU(ID_FORMAT_FONT, MyFrame::OnFont)
214 EVT_MENU(ID_FORMAT_INDENT_MORE, MyFrame::OnIndentMore)
215 EVT_MENU(ID_FORMAT_INDENT_LESS, MyFrame::OnIndentLess)
216
217 EVT_MENU(ID_FORMAT_LINE_SPACING_HALF, MyFrame::OnLineSpacingHalf)
218 EVT_MENU(ID_FORMAT_LINE_SPACING_SINGLE, MyFrame::OnLineSpacingSingle)
219 EVT_MENU(ID_FORMAT_LINE_SPACING_DOUBLE, MyFrame::OnLineSpacingDouble)
220
221 EVT_MENU(ID_FORMAT_PARAGRAPH_SPACING_MORE, MyFrame::OnParagraphSpacingMore)
222 EVT_MENU(ID_FORMAT_PARAGRAPH_SPACING_LESS, MyFrame::OnParagraphSpacingLess)
223
224 EVT_MENU(ID_VIEW_HTML, MyFrame::OnViewHTML)
225END_EVENT_TABLE()
226
227// Create a new application object: this macro will allow wxWidgets to create
228// the application object during program execution (it's better than using a
229// static object for many reasons) and also implements the accessor function
230// wxGetApp() which will return the reference of the right type (i.e. MyApp and
231// not wxApp)
232IMPLEMENT_APP(MyApp)
233
234// ============================================================================
235// implementation
236// ============================================================================
237
238// ----------------------------------------------------------------------------
239// the application class
240// ----------------------------------------------------------------------------
241
242// 'Main program' equivalent: the program execution "starts" here
243bool MyApp::OnInit()
244{
245 m_styleSheet = new wxRichTextStyleSheet;
246
247 CreateStyles();
248
249 // Add extra handlers (plain text is automatically added)
250 wxRichTextBuffer::AddHandler(new wxRichTextXMLHandler);
251 wxRichTextBuffer::AddHandler(new wxRichTextHTMLHandler);
252
253 // Add image handlers
254#if wxUSE_LIBPNG
255 wxImage::AddHandler( new wxPNGHandler );
256#endif
9a173d48 257
5d7836c4
JS
258#if wxUSE_LIBJPEG
259 wxImage::AddHandler( new wxJPEGHandler );
260#endif
261
262#if wxUSE_GIF
263 wxImage::AddHandler( new wxGIFHandler );
264#endif
265
266 // create the main application window
267 MyFrame *frame = new MyFrame(_T("wxRichTextCtrl Sample"), wxID_ANY, wxDefaultPosition, wxSize(600, 500));
268
269 // and show it (the frames, unlike simple controls, are not shown when
270 // created initially)
271 frame->Show(true);
272
273 // success: wxApp::OnRun() will be called which will enter the main message
274 // loop and the application will run. If we returned false here, the
275 // application would exit immediately.
276 return true;
277}
278
279int MyApp::OnExit()
280{
281 delete m_styleSheet;
282 return 0;
283}
284
285void MyApp::CreateStyles()
286{
287 // Paragraph styles
288
289 wxFont romanFont(12, wxROMAN, wxNORMAL, wxNORMAL);
290 wxFont swissFont(12, wxSWISS, wxNORMAL, wxNORMAL);
291
292 wxRichTextParagraphStyleDefinition* normalPara = new wxRichTextParagraphStyleDefinition(wxT("Normal"));
293 wxRichTextAttr normalAttr;
294 normalAttr.SetFontFaceName(romanFont.GetFaceName());
295 normalAttr.SetFontSize(12);
296 // Let's set all attributes for this style
297 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|
298 wxTEXT_ATTR_PARA_SPACING_BEFORE|wxTEXT_ATTR_PARA_SPACING_AFTER|wxTEXT_ATTR_LINE_SPACING|
299 wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER);
300 normalPara->SetStyle(normalAttr);
9a173d48 301
5d7836c4
JS
302 m_styleSheet->AddParagraphStyle(normalPara);
303
304 wxRichTextParagraphStyleDefinition* indentedPara = new wxRichTextParagraphStyleDefinition(wxT("Indented"));
305 wxRichTextAttr indentedAttr;
306 indentedAttr.SetFontFaceName(romanFont.GetFaceName());
307 indentedAttr.SetFontSize(12);
308 indentedAttr.SetLeftIndent(100, 0);
309 // We only want to affect indentation
310 indentedAttr.SetFlags(wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT);
311 indentedPara->SetStyle(indentedAttr);
9a173d48 312
5d7836c4
JS
313 m_styleSheet->AddParagraphStyle(indentedPara);
314
315 wxRichTextParagraphStyleDefinition* flIndentedPara = new wxRichTextParagraphStyleDefinition(wxT("First Line Indented"));
316 wxRichTextAttr flIndentedAttr;
317 flIndentedAttr.SetFontFaceName(swissFont.GetFaceName());
318 flIndentedAttr.SetFontSize(12);
319 flIndentedAttr.SetLeftIndent(100, -100);
320 // We only want to affect indentation
321 flIndentedAttr.SetFlags(wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT);
322 flIndentedPara->SetStyle(flIndentedAttr);
9a173d48 323
5d7836c4
JS
324 m_styleSheet->AddParagraphStyle(flIndentedPara);
325
326 // Character styles
327
328 wxRichTextCharacterStyleDefinition* boldDef = new wxRichTextCharacterStyleDefinition(wxT("Bold"));
329 wxRichTextAttr boldAttr;
330 boldAttr.SetFontFaceName(romanFont.GetFaceName());
331 boldAttr.SetFontSize(12);
332 boldAttr.SetFontWeight(wxBOLD);
333 // We only want to affect boldness
334 boldAttr.SetFlags(wxTEXT_ATTR_FONT_WEIGHT);
335 boldDef->SetStyle(boldAttr);
9a173d48 336
5d7836c4
JS
337 m_styleSheet->AddCharacterStyle(boldDef);
338
339 wxRichTextCharacterStyleDefinition* italicDef = new wxRichTextCharacterStyleDefinition(wxT("Italic"));
340 wxRichTextAttr italicAttr;
341 italicAttr.SetFontFaceName(romanFont.GetFaceName());
342 italicAttr.SetFontSize(12);
343 italicAttr.SetFontStyle(wxITALIC);
344 // We only want to affect italics
345 italicAttr.SetFlags(wxTEXT_ATTR_FONT_ITALIC);
346 italicDef->SetStyle(italicAttr);
9a173d48 347
5d7836c4
JS
348 m_styleSheet->AddCharacterStyle(italicDef);
349
350 wxRichTextCharacterStyleDefinition* redDef = new wxRichTextCharacterStyleDefinition(wxT("Red Bold"));
351 wxRichTextAttr redAttr;
352 redAttr.SetFontFaceName(romanFont.GetFaceName());
353 redAttr.SetFontSize(12);
354 redAttr.SetFontWeight(wxBOLD);
355 redAttr.SetTextColour(*wxRED);
356 // We only want to affect colour, weight and face
357 redAttr.SetFlags(wxTEXT_ATTR_FONT_FACE|wxTEXT_ATTR_FONT_WEIGHT|wxTEXT_ATTR_TEXT_COLOUR);
358 redDef->SetStyle(redAttr);
9a173d48 359
5d7836c4
JS
360 m_styleSheet->AddCharacterStyle(redDef);
361}
362
363// ----------------------------------------------------------------------------
364// main frame
365// ----------------------------------------------------------------------------
366
367// frame constructor
368MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
369 const wxSize& size, long style)
370 : wxFrame(NULL, id, title, pos, size, style)
371{
372 // set the frame icon
373 SetIcon(sample_xpm);
374
375 // create a menu bar
376 wxMenu *fileMenu = new wxMenu;
377
378 // the "About" item should be in the help menu
379 wxMenu *helpMenu = new wxMenu;
380 helpMenu->Append(ID_About, _T("&About...\tF1"), _T("Show about dialog"));
381
382 fileMenu->Append(wxID_OPEN, _T("&Open\tCtrl+O"), _T("Open a file"));
383 fileMenu->Append(wxID_SAVE, _T("&Save\tCtrl+S"), _T("Save a file"));
384 fileMenu->Append(wxID_SAVEAS, _T("&Save As...\tF12"), _T("Save to a new file"));
385 fileMenu->AppendSeparator();
386 fileMenu->Append(ID_VIEW_HTML, _T("&View as HTML"), _T("View HTML"));
387 fileMenu->AppendSeparator();
c4cd20cf 388 fileMenu->Append(ID_Quit, _T("E&xit\tAlt+X"), _T("Quit this program"));
5d7836c4
JS
389
390 wxMenu* editMenu = new wxMenu;
391 editMenu->Append(wxID_UNDO, _("&Undo\tCtrl+Z"));
392 editMenu->Append(wxID_REDO, _("&Redo\tCtrl+Y"));
393 editMenu->AppendSeparator();
394 editMenu->Append(wxID_CUT, _("Cu&t\tCtrl+X"));
395 editMenu->Append(wxID_COPY, _("&Copy\tCtrl+C"));
396 editMenu->Append(wxID_PASTE, _("&Paste\tCtrl+V"));
397
398 editMenu->Append(wxID_CLEAR, _("&Delete\tDel"));
399
400 editMenu->AppendSeparator();
401 editMenu->Append(wxID_SELECTALL, _("Select A&ll\tCtrl+A"));
402#if 0
403 editMenu->AppendSeparator();
404 editMenu->Append(wxID_FIND, _("&Find...\tCtrl+F"));
405 editMenu->Append(stID_FIND_REPLACE, _("&Replace...\tCtrl+R"));
406#endif
407
408 wxMenu* formatMenu = new wxMenu;
409 formatMenu->AppendCheckItem(ID_FORMAT_BOLD, _("&Bold\tCtrl+B"));
410 formatMenu->AppendCheckItem(ID_FORMAT_ITALIC, _("&Italic\tCtrl+I"));
411 formatMenu->AppendCheckItem(ID_FORMAT_UNDERLINE, _("&Underline\tCtrl+U"));
412 formatMenu->AppendSeparator();
413 formatMenu->AppendCheckItem(ID_FORMAT_ALIGN_LEFT, _("L&eft Align"));
414 formatMenu->AppendCheckItem(ID_FORMAT_ALIGN_RIGHT, _("&Right Align"));
415 formatMenu->AppendCheckItem(ID_FORMAT_ALIGN_CENTRE, _("&Centre"));
416 formatMenu->AppendSeparator();
c4cd20cf 417 formatMenu->Append(ID_FORMAT_INDENT_MORE, _("Indent &More"));
5d7836c4
JS
418 formatMenu->Append(ID_FORMAT_INDENT_LESS, _("Indent &Less"));
419 formatMenu->AppendSeparator();
420 formatMenu->Append(ID_FORMAT_PARAGRAPH_SPACING_MORE, _("Increase Paragraph &Spacing"));
421 formatMenu->Append(ID_FORMAT_PARAGRAPH_SPACING_LESS, _("Decrease &Paragraph Spacing"));
422 formatMenu->AppendSeparator();
423 formatMenu->Append(ID_FORMAT_LINE_SPACING_SINGLE, _("Normal Line Spacing"));
424 formatMenu->Append(ID_FORMAT_LINE_SPACING_HALF, _("1.5 Line Spacing"));
425 formatMenu->Append(ID_FORMAT_LINE_SPACING_DOUBLE, _("Double Line Spacing"));
426 formatMenu->AppendSeparator();
427 formatMenu->Append(ID_FORMAT_FONT, _("&Font..."));
428
429 // now append the freshly created menu to the menu bar...
430 wxMenuBar *menuBar = new wxMenuBar();
431 menuBar->Append(fileMenu, _T("&File"));
432 menuBar->Append(editMenu, _T("&Edit"));
433 menuBar->Append(formatMenu, _T("F&ormat"));
434 menuBar->Append(helpMenu, _T("&Help"));
435
436 // ... and attach this menu bar to the frame
437 SetMenuBar(menuBar);
438
439 // create a status bar just for fun (by default with 1 pane only)
9a173d48 440#if wxUSE_STATUSBAR
5d7836c4
JS
441 CreateStatusBar(2);
442 SetStatusText(_T("Welcome to wxRichTextCtrl!"));
9a173d48 443#endif
5d7836c4
JS
444
445 wxToolBar* toolBar = CreateToolBar();
446
9a173d48
WS
447 toolBar->AddTool(wxID_OPEN, wxBitmap(open_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Open"));
448 toolBar->AddTool(wxID_SAVEAS, wxBitmap(save_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Save"));
5d7836c4 449 toolBar->AddSeparator();
9a173d48
WS
450 toolBar->AddTool(wxID_CUT, wxBitmap(cut_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Cut"));
451 toolBar->AddTool(wxID_COPY, wxBitmap(copy_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Copy"));
452 toolBar->AddTool(wxID_PASTE, wxBitmap(paste_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Paste"));
5d7836c4 453 toolBar->AddSeparator();
9a173d48
WS
454 toolBar->AddTool(wxID_UNDO, wxBitmap(undo_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Undo"));
455 toolBar->AddTool(wxID_REDO, wxBitmap(redo_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Redo"));
5d7836c4 456 toolBar->AddSeparator();
9a173d48
WS
457 toolBar->AddTool(ID_FORMAT_BOLD, wxBitmap(bold_xpm), wxNullBitmap, true, -1, -1, (wxObject *) NULL, _("Bold"));
458 toolBar->AddTool(ID_FORMAT_ITALIC, wxBitmap(italic_xpm), wxNullBitmap, true, -1, -1, (wxObject *) NULL, _("Italic"));
459 toolBar->AddTool(ID_FORMAT_UNDERLINE, wxBitmap(underline_xpm), wxNullBitmap, true, -1, -1, (wxObject *) NULL, _("Underline"));
5d7836c4 460 toolBar->AddSeparator();
9a173d48
WS
461 toolBar->AddTool(ID_FORMAT_ALIGN_LEFT, wxBitmap(alignleft_xpm), wxNullBitmap, true, -1, -1, (wxObject *) NULL, _("Align Left"));
462 toolBar->AddTool(ID_FORMAT_ALIGN_CENTRE, wxBitmap(centre_xpm), wxNullBitmap, true, -1, -1, (wxObject *) NULL, _("Centre"));
463 toolBar->AddTool(ID_FORMAT_ALIGN_RIGHT, wxBitmap(alignright_xpm), wxNullBitmap, true, -1, -1, (wxObject *) NULL, _("Align Right"));
5d7836c4 464 toolBar->AddSeparator();
9a173d48
WS
465 toolBar->AddTool(ID_FORMAT_INDENT_LESS, wxBitmap(indentless_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Indent Less"));
466 toolBar->AddTool(ID_FORMAT_INDENT_MORE, wxBitmap(indentmore_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Indent More"));
5d7836c4 467 toolBar->AddSeparator();
9a173d48 468 toolBar->AddTool(ID_FORMAT_FONT, wxBitmap(font_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Font"));
5d7836c4
JS
469
470 toolBar->Realize();
471
c59f6793 472 wxSplitterWindow* splitter = new wxSplitterWindow(this, wxID_ANY, wxDefaultPosition, GetClientSize(), wxSP_NO_XP_THEME|wxSP_3D|wxSP_LIVE_UPDATE);
5d7836c4
JS
473
474 wxFont textFont = wxFont(12, wxROMAN, wxNORMAL, wxNORMAL);
475 wxFont boldFont = wxFont(12, wxROMAN, wxNORMAL, wxBOLD);
476 wxFont italicFont = wxFont(12, wxROMAN, wxITALIC, wxNORMAL);
477
478 m_richTextCtrl = new wxRichTextCtrl(splitter, wxID_ANY, wxDefaultPosition, wxSize(200, 200), wxVSCROLL|wxHSCROLL|wxNO_BORDER);
ff2baa25
JS
479 wxFont font(12, wxROMAN, wxNORMAL, wxNORMAL);
480
481#ifdef __WXMAC__
482 font.SetNoAntiAliasing(true);
483#endif
484 m_richTextCtrl->SetFont(font);
5d7836c4
JS
485
486 wxRichTextStyleListBox* styleListBox = new wxRichTextStyleListBox(splitter, wxID_ANY);
487 splitter->SplitVertically(m_richTextCtrl, styleListBox, 400);
488
c59f6793
JS
489 splitter->UpdateSize();
490
5d7836c4
JS
491 styleListBox->SetStyleSheet(wxGetApp().GetStyleSheet());
492 styleListBox->SetRichTextCtrl(m_richTextCtrl);
493 styleListBox->UpdateStyles();
494
495 wxRichTextCtrl& r = *m_richTextCtrl;
496
497 r.BeginSuppressUndo();
498
499 r.BeginParagraphSpacing(0, 20);
500
501 r.BeginAlignment(wxTEXT_ALIGNMENT_CENTRE);
502 r.BeginBold();
503
504 r.BeginFontSize(14);
505 r.WriteText(wxT("Welcome to wxRichTextCtrl, a wxWidgets control for editing and presenting styled text and images"));
506 r.EndFontSize();
507 r.Newline();
508
509 r.BeginItalic();
510 r.WriteText(wxT("by Julian Smart"));
511 r.EndItalic();
512
513 r.EndBold();
514
515 r.Newline();
516 r.WriteImage(wxBitmap(zebra_xpm));
517
518 r.EndAlignment();
519
520 r.Newline();
521 r.Newline();
522
523 r.WriteText(wxT("What can you do with this thing? "));
524 r.WriteImage(wxBitmap(smiley_xpm));
525 r.WriteText(wxT(" Well, you can change text "));
526
527 r.BeginTextColour(wxColour(255, 0, 0));
528 r.WriteText(wxT("colour, like this red bit."));
529 r.EndTextColour();
530
531 r.BeginTextColour(wxColour(0, 0, 255));
532 r.WriteText(wxT(" And this blue bit."));
533 r.EndTextColour();
534
535 r.WriteText(wxT(" Naturally you can make things "));
536 r.BeginBold();
537 r.WriteText(wxT("bold "));
538 r.EndBold();
539 r.BeginItalic();
540 r.WriteText(wxT("or italic "));
541 r.EndItalic();
542 r.BeginUnderline();
543 r.WriteText(wxT("or underlined."));
544 r.EndUnderline();
545
546 r.BeginFontSize(14);
547 r.WriteText(wxT(" Different font sizes on the same line is allowed, too."));
548 r.EndFontSize();
549
550 r.WriteText(wxT(" Next we'll show an indented paragraph."));
551
552 r.BeginLeftIndent(60);
553 r.Newline();
554
555 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."));
556 r.EndLeftIndent();
557
558 r.Newline();
559
560 r.WriteText(wxT("Next, we'll show a first-line indent, achieved using BeginLeftIndent(100, -40)."));
561
562 r.BeginLeftIndent(100, -40);
563 r.Newline();
564
565 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."));
566 r.EndLeftIndent();
567
568 r.Newline();
569
570 r.WriteText(wxT("Numbered bullets are possible, again using subindents:"));
571
572 r.BeginNumberedBullet(1, 100, 60);
573 r.Newline();
574
575 r.WriteText(wxT("This is my first item. Note that wxRichTextCtrl doesn't automatically do numbering, but this will be added later."));
576 r.EndNumberedBullet();
577
578 r.BeginNumberedBullet(2, 100, 60);
579 r.Newline();
580
581 r.WriteText(wxT("This is my second item."));
582 r.EndNumberedBullet();
583
584 r.Newline();
585
586 r.WriteText(wxT("The following paragraph is right-indented:"));
587
588 r.BeginRightIndent(200);
589 r.Newline();
590
591 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."));
592 r.EndRightIndent();
593
594 r.Newline();
595
596 r.WriteText(wxT("The following paragraph is right-aligned with 1.5 line spacing:"));
597
598 r.BeginAlignment(wxTEXT_ALIGNMENT_RIGHT);
599 r.BeginLineSpacing(wxTEXT_ATTR_LINE_SPACING_HALF);
600 r.Newline();
601
602 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."));
603 r.EndLineSpacing();
604 r.EndAlignment();
605
606 r.Newline();
607 r.WriteText(wxT("Other notable features of wxRichTextCtrl include:"));
608
609 r.BeginSymbolBullet(wxT('*'), 100, 60);
610 r.Newline();
611 r.WriteText(wxT("Compatibility with wxTextCtrl API"));
612 r.EndSymbolBullet();
613
614 r.BeginSymbolBullet(wxT('*'), 100, 60);
615 r.Newline();
616 r.WriteText(wxT("Easy stack-based BeginXXX()...EndXXX() style setting in addition to SetStyle()"));
617 r.EndSymbolBullet();
618
619 r.BeginSymbolBullet(wxT('*'), 100, 60);
620 r.Newline();
621 r.WriteText(wxT("XML loading and saving"));
622 r.EndSymbolBullet();
623
624 r.BeginSymbolBullet(wxT('*'), 100, 60);
625 r.Newline();
626 r.WriteText(wxT("Undo/Redo, with batching option and Undo suppressing"));
627 r.EndSymbolBullet();
628
629 r.BeginSymbolBullet(wxT('*'), 100, 60);
630 r.Newline();
631 r.WriteText(wxT("Clipboard copy and paste"));
632 r.EndSymbolBullet();
633
634 r.BeginSymbolBullet(wxT('*'), 100, 60);
635 r.Newline();
636 r.WriteText(wxT("wxRichTextStyleSheet with named character and paragraph styles, and control for applying named styles"));
637 r.EndSymbolBullet();
638
639 r.BeginSymbolBullet(wxT('*'), 100, 60);
640 r.Newline();
641 r.WriteText(wxT("A design that can easily be extended to other content types, ultimately with text boxes, tables, controls, and so on"));
642 r.EndSymbolBullet();
643
644 r.Newline();
645
646 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!"));
647
648 r.EndParagraphSpacing();
649
650 r.EndSuppressUndo();
651}
652
653
654// event handlers
655
656void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
657{
658 // true is to force the frame to close
659 Close(true);
660}
661
662void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
663{
664 wxString msg;
665 msg.Printf( _T("This is a demo for wxRichTextCtrl, a control for editing styled text.\n(c) Julian Smart, 2005"));
666 wxMessageBox(msg, _T("About wxRichTextCtrl Sample"), wxOK | wxICON_INFORMATION, this);
667}
668
669// Forward command events to the current rich text control, if any
670bool MyFrame::ProcessEvent(wxEvent& event)
671{
672 if (event.IsCommandEvent() && !event.IsKindOf(CLASSINFO(wxChildFocusEvent)))
673 {
674 // Problem: we can get infinite recursion because the events
675 // climb back up to this frame, and repeat.
676 // Assume that command events don't cause another command event
677 // to be called, so we can rely on inCommand not being overwritten
678
679 static int s_eventType = 0;
680 static wxWindowID s_id = 0;
681
682 if (s_id != event.GetId() && s_eventType != event.GetEventType())
683 {
684 s_eventType = event.GetEventType();
685 s_id = event.GetId();
9a173d48 686
5d7836c4
JS
687 wxWindow* focusWin = wxFindFocusDescendant(this);
688 if (focusWin && focusWin->ProcessEvent(event))
689 {
690 //s_command = NULL;
691 s_eventType = 0;
692 s_id = 0;
9a173d48 693 return true;
5d7836c4
JS
694 }
695
696 s_eventType = 0;
697 s_id = 0;
698 }
699 else
700 {
9a173d48 701 return false;
5d7836c4
JS
702 }
703 }
704
705 return wxFrame::ProcessEvent(event);
706}
707
011b3dcb 708void MyFrame::OnOpen(wxCommandEvent& WXUNUSED(event))
5d7836c4 709{
9a173d48
WS
710 wxString path;
711 wxString filename;
1e967276
JS
712 wxArrayInt fileTypes;
713
714 wxString filter = wxRichTextBuffer::GetExtWildcard(false, false, & fileTypes);
9a173d48 715 if (!filter.empty())
5d7836c4
JS
716 filter += wxT("|");
717 filter += wxT("All files (*.*)|*.*");
718
5d7836c4
JS
719 wxFileDialog dialog(this,
720 _("Choose a filename"),
721 path,
722 filename,
723 filter,
724 wxOPEN);
725
726 if (dialog.ShowModal() == wxID_OK)
727 {
728 wxString path = dialog.GetPath();
9a173d48
WS
729
730 if (!path.empty())
5d7836c4 731 {
1e967276 732 int filterIndex = dialog.GetFilterIndex();
dbf38e88
WS
733 int fileType = (filterIndex < (int) fileTypes.GetCount())
734 ? fileTypes[filterIndex]
735 : wxRICHTEXT_TYPE_TEXT;
1e967276 736 m_richTextCtrl->LoadFile(path, fileType);
5d7836c4
JS
737 }
738 }
739}
740
741void MyFrame::OnSave(wxCommandEvent& event)
742{
9a173d48 743 if (m_richTextCtrl->GetFilename().empty())
5d7836c4
JS
744 {
745 OnSaveAs(event);
746 return;
747 }
748 m_richTextCtrl->SaveFile();
749}
750
011b3dcb 751void MyFrame::OnSaveAs(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
752{
753 wxString filter = wxRichTextBuffer::GetExtWildcard(false, true);
9a173d48
WS
754 wxString path;
755 wxString filename;
5d7836c4
JS
756
757 wxFileDialog dialog(this,
758 _("Choose a filename"),
759 path,
760 filename,
761 filter,
762 wxSAVE);
763
764 if (dialog.ShowModal() == wxID_OK)
765 {
766 wxString path = dialog.GetPath();
9a173d48
WS
767
768 if (!path.empty())
5d7836c4
JS
769 {
770 m_richTextCtrl->SaveFile(path);
771 }
772 }
773}
774
011b3dcb 775void MyFrame::OnBold(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
776{
777 m_richTextCtrl->ApplyBoldToSelection();
778}
779
011b3dcb 780void MyFrame::OnItalic(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
781{
782 m_richTextCtrl->ApplyItalicToSelection();
783}
784
011b3dcb 785void MyFrame::OnUnderline(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
786{
787 m_richTextCtrl->ApplyUnderlineToSelection();
788}
789
790
791void MyFrame::OnUpdateBold(wxUpdateUIEvent& event)
792{
793 event.Check(m_richTextCtrl->IsSelectionBold());
794}
795
796void MyFrame::OnUpdateItalic(wxUpdateUIEvent& event)
797{
798 event.Check(m_richTextCtrl->IsSelectionItalics());
799}
800
801void MyFrame::OnUpdateUnderline(wxUpdateUIEvent& event)
802{
803 event.Check(m_richTextCtrl->IsSelectionUnderlined());
804}
805
011b3dcb 806void MyFrame::OnAlignLeft(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
807{
808 m_richTextCtrl->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_LEFT);
809}
810
011b3dcb 811void MyFrame::OnAlignCentre(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
812{
813 m_richTextCtrl->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_CENTRE);
814}
815
011b3dcb 816void MyFrame::OnAlignRight(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
817{
818 m_richTextCtrl->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_RIGHT);
819}
820
821void MyFrame::OnUpdateAlignLeft(wxUpdateUIEvent& event)
822{
823 event.Check(m_richTextCtrl->IsSelectionAligned(wxTEXT_ALIGNMENT_LEFT));
824}
825
826void MyFrame::OnUpdateAlignCentre(wxUpdateUIEvent& event)
827{
828 event.Check(m_richTextCtrl->IsSelectionAligned(wxTEXT_ALIGNMENT_CENTRE));
829}
830
831void MyFrame::OnUpdateAlignRight(wxUpdateUIEvent& event)
832{
833 event.Check(m_richTextCtrl->IsSelectionAligned(wxTEXT_ALIGNMENT_RIGHT));
834}
835
011b3dcb 836void MyFrame::OnFont(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
837{
838 if (!m_richTextCtrl->HasSelection())
839 return;
840
841 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
842 wxFontData fontData;
843
844 wxTextAttrEx attr;
845 attr.SetFlags(wxTEXT_ATTR_FONT);
846
847 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
848 fontData.SetInitialFont(attr.GetFont());
849
850 wxFontDialog dialog(this, fontData);
851 if (dialog.ShowModal() == wxID_OK)
852 {
853 fontData = dialog.GetFontData();
854 attr.SetFlags(wxTEXT_ATTR_FONT);
855 attr.SetFont(fontData.GetChosenFont());
856 if (attr.GetFont().Ok())
857 {
858 m_richTextCtrl->SetStyle(range, attr);
859 }
860 }
861}
862
011b3dcb 863void MyFrame::OnIndentMore(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
864{
865 wxTextAttrEx attr;
866 attr.SetFlags(wxTEXT_ATTR_LEFT_INDENT);
867
868 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
869 {
870 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
871 if (m_richTextCtrl->HasSelection())
872 range = m_richTextCtrl->GetSelectionRange();
873
874 wxFontData fontData;
875 attr.SetLeftIndent(attr.GetLeftIndent() + 100);
876
877 attr.SetFlags(wxTEXT_ATTR_LEFT_INDENT);
878 m_richTextCtrl->SetStyle(range, attr);
879 }
880}
881
011b3dcb 882void MyFrame::OnIndentLess(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
883{
884 wxTextAttrEx attr;
885 attr.SetFlags(wxTEXT_ATTR_LEFT_INDENT);
886
887 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
888 {
889 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
890 if (m_richTextCtrl->HasSelection())
891 range = m_richTextCtrl->GetSelectionRange();
892
893 if (attr.GetLeftIndent() >= 100)
894 {
895 wxFontData fontData;
896 attr.SetLeftIndent(attr.GetLeftIndent() - 100);
9a173d48 897
5d7836c4
JS
898 m_richTextCtrl->SetStyle(range, attr);
899 }
900 }
901}
902
011b3dcb 903void MyFrame::OnLineSpacingHalf(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
904{
905 wxTextAttrEx attr;
906 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
907
908 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
909 {
910 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
911 if (m_richTextCtrl->HasSelection())
912 range = m_richTextCtrl->GetSelectionRange();
913
914 wxFontData fontData;
915 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
916 attr.SetLineSpacing(15);
9a173d48 917
5d7836c4
JS
918 m_richTextCtrl->SetStyle(range, attr);
919 }
920}
921
011b3dcb 922void MyFrame::OnLineSpacingDouble(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
923{
924 wxTextAttrEx attr;
925 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
926
927 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
928 {
929 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
930 if (m_richTextCtrl->HasSelection())
931 range = m_richTextCtrl->GetSelectionRange();
932
933 wxFontData fontData;
934 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
935 attr.SetLineSpacing(20);
9a173d48 936
5d7836c4
JS
937 m_richTextCtrl->SetStyle(range, attr);
938 }
939}
940
011b3dcb 941void MyFrame::OnLineSpacingSingle(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
942{
943 wxTextAttrEx attr;
944 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
945
946 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
947 {
948 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
949 if (m_richTextCtrl->HasSelection())
950 range = m_richTextCtrl->GetSelectionRange();
951
952 wxFontData fontData;
953 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
954 attr.SetLineSpacing(0); // Can also use 10
9a173d48 955
5d7836c4
JS
956 m_richTextCtrl->SetStyle(range, attr);
957 }
958}
959
011b3dcb 960void MyFrame::OnParagraphSpacingMore(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
961{
962 wxTextAttrEx attr;
963 attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER);
964
965 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
966 {
967 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
968 if (m_richTextCtrl->HasSelection())
969 range = m_richTextCtrl->GetSelectionRange();
970
971 wxFontData fontData;
972 attr.SetParagraphSpacingAfter(attr.GetParagraphSpacingAfter() + 20);
973
974 attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER);
975 m_richTextCtrl->SetStyle(range, attr);
976 }
977}
978
011b3dcb 979void MyFrame::OnParagraphSpacingLess(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
980{
981 wxTextAttrEx attr;
982 attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER);
983
984 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
985 {
986 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
987 if (m_richTextCtrl->HasSelection())
988 range = m_richTextCtrl->GetSelectionRange();
989
990 if (attr.GetParagraphSpacingAfter() >= 20)
991 {
992 wxFontData fontData;
993 attr.SetParagraphSpacingAfter(attr.GetParagraphSpacingAfter() - 20);
9a173d48 994
5d7836c4
JS
995 attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER);
996 m_richTextCtrl->SetStyle(range, attr);
997 }
998 }
999}
1000
011b3dcb 1001void MyFrame::OnViewHTML(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1002{
1003 wxDialog dialog(this, wxID_ANY, _("HTML"), wxDefaultPosition, wxSize(500, 400), wxDEFAULT_DIALOG_STYLE);
1004
1005 wxBoxSizer* boxSizer = new wxBoxSizer(wxVERTICAL);
1006 dialog.SetSizer(boxSizer);
1007
1008 wxHtmlWindow* win = new wxHtmlWindow(& dialog, wxID_ANY, wxDefaultPosition, wxSize(500, 400), wxSUNKEN_BORDER);
1009 boxSizer->Add(win, 1, wxALL, 5);
1010
1011 wxButton* cancelButton = new wxButton(& dialog, wxID_CANCEL, wxT("&Close"));
1012 boxSizer->Add(cancelButton, 0, wxALL|wxCENTRE, 5);
1013
1014 wxString text;
1015 wxStringOutputStream strStream(& text);
1016
1017 wxRichTextHTMLHandler htmlHandler;
1018 if (htmlHandler.SaveFile(& m_richTextCtrl->GetBuffer(), strStream))
1019 {
1020 win->SetPage(text);
1021 }
1022
1023 boxSizer->Fit(& dialog);
1024
1025 dialog.ShowModal();
1026}