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