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