]> git.saurik.com Git - wxWidgets.git/blame - samples/richtext/richtext.cpp
Fix wrong references to wxImageList description in XRC format docs.
[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
5d7836c4
JS
7// Copyright: (c) Julian Smart
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// For compilers that support precompilation, includes "wx/wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26// for all others, include the necessary headers (this file is usually all you
27// need because it includes almost all "standard" wxWidgets headers)
28#ifndef WX_PRECOMP
29 #include "wx/wx.h"
30#endif
31
32#include "wx/fontdlg.h"
33#include "wx/splitter.h"
34#include "wx/sstream.h"
35#include "wx/html/htmlwin.h"
bec80f4f 36#include "wx/stopwatch.h"
b4e415df 37#include "wx/sysopt.h"
5d7836c4 38
720cc10a
JS
39#if wxUSE_FILESYSTEM
40#include "wx/filesys.h"
41#include "wx/fs_mem.h"
42#endif
43
2569ebc2
JS
44#if wxUSE_HELP
45#include "wx/cshelp.h"
46#endif
47
e7092398 48#ifndef wxHAS_IMAGES_IN_RESOURCES
1226b3b3
WS
49 #include "../sample.xpm"
50#endif
51
5d7836c4
JS
52#include "bitmaps/smiley.xpm"
53// #include "bitmaps/idea.xpm"
54#include "bitmaps/zebra.xpm"
55
56#include "bitmaps/open.xpm"
57#include "bitmaps/save.xpm"
58#include "bitmaps/copy.xpm"
59#include "bitmaps/cut.xpm"
60#include "bitmaps/paste.xpm"
61#include "bitmaps/undo.xpm"
62#include "bitmaps/redo.xpm"
63#include "bitmaps/bold.xpm"
64#include "bitmaps/italic.xpm"
65#include "bitmaps/underline.xpm"
66
67#include "bitmaps/alignleft.xpm"
68#include "bitmaps/alignright.xpm"
69#include "bitmaps/centre.xpm"
70#include "bitmaps/font.xpm"
71#include "bitmaps/indentless.xpm"
72#include "bitmaps/indentmore.xpm"
73
011b3dcb
JS
74#include "wx/richtext/richtextctrl.h"
75#include "wx/richtext/richtextstyles.h"
76#include "wx/richtext/richtextxml.h"
b71e9aa4 77#include "wx/richtext/richtexthtml.h"
8c9c49a1
JS
78#include "wx/richtext/richtextformatdlg.h"
79#include "wx/richtext/richtextsymboldlg.h"
e4723634 80#include "wx/richtext/richtextstyledlg.h"
8881d9f0 81#include "wx/richtext/richtextprint.h"
cdaed652 82#include "wx/richtext/richtextimagedlg.h"
5d7836c4 83
32423dd8
JS
84// A custom field type
85class wxRichTextFieldTypePropertiesTest: public wxRichTextFieldTypeStandard
86{
87public:
88 wxRichTextFieldTypePropertiesTest(const wxString& name, const wxString& label, int displayStyle = wxRICHTEXT_FIELD_STYLE_RECTANGLE):
89 wxRichTextFieldTypeStandard(name, label, displayStyle)
90 {
91 }
92 wxRichTextFieldTypePropertiesTest(const wxString& name, const wxBitmap& bitmap, int displayStyle = wxRICHTEXT_FIELD_STYLE_RECTANGLE):
93 wxRichTextFieldTypeStandard(name, bitmap, displayStyle)
94 {
95 }
96
97 virtual bool CanEditProperties(wxRichTextField* WXUNUSED(obj)) const { return true; }
98 virtual bool EditProperties(wxRichTextField* WXUNUSED(obj), wxWindow* WXUNUSED(parent), wxRichTextBuffer* WXUNUSED(buffer))
99 {
100 wxString label = GetLabel();
101 wxMessageBox(wxString::Format(wxT("Editing %s"), label.c_str()));
102 return true;
103 }
104
105 virtual wxString GetPropertiesMenuLabel(wxRichTextField* WXUNUSED(obj)) const
106 {
107 return GetLabel();
108 }
109};
110
111// A custom composite field type
112class wxRichTextFieldTypeCompositeTest: public wxRichTextFieldTypePropertiesTest
113{
114public:
115 wxRichTextFieldTypeCompositeTest(const wxString& name, const wxString& label):
116 wxRichTextFieldTypePropertiesTest(name, label, wxRICHTEXT_FIELD_STYLE_COMPOSITE)
117 {
118 }
119
120 virtual bool UpdateField(wxRichTextBuffer* buffer, wxRichTextField* obj)
121 {
122 if (buffer)
123 {
124 wxRichTextAttr attr(buffer->GetAttributes());
125 attr.GetTextBoxAttr().Reset();
126 attr.SetParagraphSpacingAfter(0);
127 attr.SetLineSpacing(10);
128 obj->SetAttributes(attr);
129 }
130 obj->GetChildren().Clear();
131 wxRichTextParagraph* para = new wxRichTextParagraph;
132 wxRichTextPlainText* text = new wxRichTextPlainText(GetLabel());
133 para->AppendChild(text);
134 obj->AppendChild(para);
135 return true;
136 }
137};
138
5d7836c4
JS
139// ----------------------------------------------------------------------------
140// resources
141// ----------------------------------------------------------------------------
142
143// ----------------------------------------------------------------------------
144// private classes
145// ----------------------------------------------------------------------------
146
cc2aecde
JS
147// Define a new application type, each program should derive a class from wxApp
148class MyRichTextCtrl: public wxRichTextCtrl
149{
150public:
151 MyRichTextCtrl( wxWindow* parent, wxWindowID id = -1, const wxString& value = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
152 long style = wxRE_MULTILINE, const wxValidator& validator = wxDefaultValidator, const wxString& name = wxTextCtrlNameStr):
153 wxRichTextCtrl(parent, id, value, pos, size, style, validator, name)
154 {
155 m_lockId = 0;
156 m_locked = false;
157 }
158
159 void SetLockId(long id) { m_lockId = id; }
160 long GetLockId() const { return m_lockId; }
161
162 void BeginLock() { m_lockId ++; m_locked = true; }
163 void EndLock() { m_locked = false; }
164 bool IsLocked() const { return m_locked; }
165
166 static void SetEnhancedDrawingHandler();
167
168 /**
169 Prepares the content just before insertion (or after buffer reset). Called by the same function in wxRichTextBuffer.
170 Currently is only called if undo mode is on.
171 */
172 virtual void PrepareContent(wxRichTextParagraphLayoutBox& container);
173
174 /**
175 Can we delete this range?
176 Sends an event to the control.
177 */
178 virtual bool CanDeleteRange(wxRichTextParagraphLayoutBox& container, const wxRichTextRange& range) const;
179
180 /**
181 Can we insert content at this position?
182 Sends an event to the control.
183 */
184 virtual bool CanInsertContent(wxRichTextParagraphLayoutBox& container, long pos) const;
185
f4ac09e8
JS
186 /**
187 Finds a table, either selected or near the cursor
188 */
189 wxRichTextTable* FindTable() const;
190
191 /**
192 Helper for FindTable()
193 */
194 wxRichTextObject* FindCurrentPosition() const;
195
cc2aecde
JS
196 long m_lockId;
197 bool m_locked;
198};
199
5d7836c4
JS
200// Define a new application type, each program should derive a class from wxApp
201class MyApp : public wxApp
202{
203public:
204 // override base class virtuals
205 // ----------------------------
206
207 // this one is called on application startup and is a good place for the app
208 // initialization (doing it here and not in the ctor allows to have an error
209 // return: if OnInit() returns false, the application terminates)
210 virtual bool OnInit();
211 virtual int OnExit();
212
213 void CreateStyles();
214
215 wxRichTextStyleSheet* GetStyleSheet() const { return m_styleSheet; }
8881d9f0 216 wxRichTextPrinting* GetPrinting() const { return m_printing; }
5d7836c4 217
8881d9f0
JS
218 wxRichTextStyleSheet* m_styleSheet;
219 wxRichTextPrinting* m_printing;
5d7836c4
JS
220};
221
222// Define a new frame type: this is going to be our main frame
223class MyFrame : public wxFrame
224{
225public:
226 // ctor(s)
227 MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos = wxDefaultPosition,
228 const wxSize& size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE);
229
230 // event handlers (these functions should _not_ be virtual)
231 void OnQuit(wxCommandEvent& event);
232 void OnAbout(wxCommandEvent& event);
233
234 void OnOpen(wxCommandEvent& event);
235 void OnSave(wxCommandEvent& event);
236 void OnSaveAs(wxCommandEvent& event);
237
238 void OnBold(wxCommandEvent& event);
239 void OnItalic(wxCommandEvent& event);
240 void OnUnderline(wxCommandEvent& event);
241
75936ec6
JS
242 void OnStrikethrough(wxCommandEvent& event);
243 void OnSuperscript(wxCommandEvent& event);
244 void OnSubscript(wxCommandEvent& event);
245
5d7836c4
JS
246 void OnUpdateBold(wxUpdateUIEvent& event);
247 void OnUpdateItalic(wxUpdateUIEvent& event);
248 void OnUpdateUnderline(wxUpdateUIEvent& event);
75936ec6
JS
249 void OnUpdateStrikethrough(wxUpdateUIEvent& event);
250 void OnUpdateSuperscript(wxUpdateUIEvent& event);
251 void OnUpdateSubscript(wxUpdateUIEvent& event);
5d7836c4
JS
252
253 void OnAlignLeft(wxCommandEvent& event);
254 void OnAlignCentre(wxCommandEvent& event);
255 void OnAlignRight(wxCommandEvent& event);
256
257 void OnUpdateAlignLeft(wxUpdateUIEvent& event);
258 void OnUpdateAlignCentre(wxUpdateUIEvent& event);
259 void OnUpdateAlignRight(wxUpdateUIEvent& event);
260
5d7836c4
JS
261 void OnIndentMore(wxCommandEvent& event);
262 void OnIndentLess(wxCommandEvent& event);
263
8c9c49a1 264 void OnFont(wxCommandEvent& event);
cdaed652
VZ
265 void OnImage(wxCommandEvent& event);
266 void OnUpdateImage(wxUpdateUIEvent& event);
8c9c49a1
JS
267 void OnParagraph(wxCommandEvent& event);
268 void OnFormat(wxCommandEvent& event);
269 void OnUpdateFormat(wxUpdateUIEvent& event);
270
271 void OnInsertSymbol(wxCommandEvent& event);
272
5d7836c4
JS
273 void OnLineSpacingHalf(wxCommandEvent& event);
274 void OnLineSpacingDouble(wxCommandEvent& event);
275 void OnLineSpacingSingle(wxCommandEvent& event);
276
277 void OnParagraphSpacingMore(wxCommandEvent& event);
278 void OnParagraphSpacingLess(wxCommandEvent& event);
279
082cfe55 280 void OnNumberList(wxCommandEvent& event);
e4723634 281 void OnBulletsAndNumbering(wxCommandEvent& event);
082cfe55
JS
282 void OnItemizeList(wxCommandEvent& event);
283 void OnRenumberList(wxCommandEvent& event);
284 void OnPromoteList(wxCommandEvent& event);
285 void OnDemoteList(wxCommandEvent& event);
286 void OnClearList(wxCommandEvent& event);
287
f4ac09e8
JS
288 void OnTableAddColumn(wxCommandEvent& event);
289 void OnTableAddRow(wxCommandEvent& event);
290 void OnTableDeleteColumn(wxCommandEvent& event);
291 void OnTableDeleteRow(wxCommandEvent& event);
292 void OnTableFocusedUpdateUI(wxUpdateUIEvent& event);
293 void OnTableHasCellsUpdateUI(wxUpdateUIEvent& event);
294
99404ab0
JS
295 void OnReload(wxCommandEvent& event);
296
5d7836c4
JS
297 void OnViewHTML(wxCommandEvent& event);
298
fe5aa22c 299 void OnSwitchStyleSheets(wxCommandEvent& event);
e4723634 300 void OnManageStyles(wxCommandEvent& event);
fe5aa22c 301
720cc10a
JS
302 void OnInsertURL(wxCommandEvent& event);
303 void OnURL(wxTextUrlEvent& event);
304 void OnStyleSheetReplacing(wxRichTextEvent& event);
305
8881d9f0
JS
306 void OnPrint(wxCommandEvent& event);
307 void OnPreview(wxCommandEvent& event);
308 void OnPageSetup(wxCommandEvent& event);
309
cdaed652 310 void OnInsertImage(wxCommandEvent& event);
32423dd8
JS
311
312 void OnSetFontScale(wxCommandEvent& event);
313 void OnSetDimensionScale(wxCommandEvent& event);
004867db
FM
314protected:
315
5d7836c4
JS
316 // Forward command events to the current rich text control, if any
317 bool ProcessEvent(wxEvent& event);
318
99404ab0
JS
319 // Write text
320 void WriteInitialText();
321
5d7836c4
JS
322private:
323 // any class wishing to process wxWidgets events must use this macro
324 DECLARE_EVENT_TABLE()
325
cc2aecde 326 MyRichTextCtrl* m_richTextCtrl;
5d7836c4
JS
327};
328
329// ----------------------------------------------------------------------------
330// constants
331// ----------------------------------------------------------------------------
332
333// IDs for the controls and the menu commands
334enum
335{
336 // menu items
337 ID_Quit = wxID_EXIT,
338 ID_About = wxID_ABOUT,
339
340 ID_FORMAT_BOLD = 100,
341 ID_FORMAT_ITALIC,
342 ID_FORMAT_UNDERLINE,
75936ec6
JS
343 ID_FORMAT_STRIKETHROUGH,
344 ID_FORMAT_SUPERSCRIPT,
345 ID_FORMAT_SUBSCRIPT,
5d7836c4 346 ID_FORMAT_FONT,
cdaed652 347 ID_FORMAT_IMAGE,
8c9c49a1
JS
348 ID_FORMAT_PARAGRAPH,
349 ID_FORMAT_CONTENT,
350
99404ab0
JS
351 ID_RELOAD,
352
8c9c49a1 353 ID_INSERT_SYMBOL,
720cc10a 354 ID_INSERT_URL,
cdaed652 355 ID_INSERT_IMAGE,
5d7836c4
JS
356
357 ID_FORMAT_ALIGN_LEFT,
358 ID_FORMAT_ALIGN_CENTRE,
359 ID_FORMAT_ALIGN_RIGHT,
360
361 ID_FORMAT_INDENT_MORE,
362 ID_FORMAT_INDENT_LESS,
363
364 ID_FORMAT_PARAGRAPH_SPACING_MORE,
365 ID_FORMAT_PARAGRAPH_SPACING_LESS,
366
367 ID_FORMAT_LINE_SPACING_HALF,
368 ID_FORMAT_LINE_SPACING_DOUBLE,
369 ID_FORMAT_LINE_SPACING_SINGLE,
370
082cfe55 371 ID_FORMAT_NUMBER_LIST,
e4723634 372 ID_FORMAT_BULLETS_AND_NUMBERING,
082cfe55
JS
373 ID_FORMAT_ITEMIZE_LIST,
374 ID_FORMAT_RENUMBER_LIST,
375 ID_FORMAT_PROMOTE_LIST,
376 ID_FORMAT_DEMOTE_LIST,
377 ID_FORMAT_CLEAR_LIST,
378
f4ac09e8
JS
379 ID_TABLE_ADD_COLUMN,
380 ID_TABLE_ADD_ROW,
381 ID_TABLE_DELETE_COLUMN,
382 ID_TABLE_DELETE_ROW,
383
32423dd8
JS
384 ID_SET_FONT_SCALE,
385 ID_SET_DIMENSION_SCALE,
386
fe5aa22c
JS
387 ID_VIEW_HTML,
388 ID_SWITCH_STYLE_SHEETS,
e4723634 389 ID_MANAGE_STYLES,
fe5aa22c 390
8881d9f0
JS
391 ID_PRINT,
392 ID_PREVIEW,
393 ID_PAGE_SETUP,
394
fe5aa22c
JS
395 ID_RICHTEXT_CTRL,
396 ID_RICHTEXT_STYLE_LIST,
397 ID_RICHTEXT_STYLE_COMBO
5d7836c4
JS
398};
399
400// ----------------------------------------------------------------------------
401// event tables and other macros for wxWidgets
402// ----------------------------------------------------------------------------
403
404// the event tables connect the wxWidgets events with the functions (event
405// handlers) which process them. It can be also done at run-time, but for the
406// simple menu events like this the static method is much simpler.
407BEGIN_EVENT_TABLE(MyFrame, wxFrame)
408 EVT_MENU(ID_Quit, MyFrame::OnQuit)
409 EVT_MENU(ID_About, MyFrame::OnAbout)
410
411 EVT_MENU(wxID_OPEN, MyFrame::OnOpen)
412 EVT_MENU(wxID_SAVE, MyFrame::OnSave)
413 EVT_MENU(wxID_SAVEAS, MyFrame::OnSaveAs)
414
415 EVT_MENU(ID_FORMAT_BOLD, MyFrame::OnBold)
416 EVT_MENU(ID_FORMAT_ITALIC, MyFrame::OnItalic)
417 EVT_MENU(ID_FORMAT_UNDERLINE, MyFrame::OnUnderline)
418
75936ec6
JS
419 EVT_MENU(ID_FORMAT_STRIKETHROUGH, MyFrame::OnStrikethrough)
420 EVT_MENU(ID_FORMAT_SUPERSCRIPT, MyFrame::OnSuperscript)
421 EVT_MENU(ID_FORMAT_SUBSCRIPT, MyFrame::OnSubscript)
422
5d7836c4
JS
423 EVT_UPDATE_UI(ID_FORMAT_BOLD, MyFrame::OnUpdateBold)
424 EVT_UPDATE_UI(ID_FORMAT_ITALIC, MyFrame::OnUpdateItalic)
425 EVT_UPDATE_UI(ID_FORMAT_UNDERLINE, MyFrame::OnUpdateUnderline)
426
75936ec6
JS
427 EVT_UPDATE_UI(ID_FORMAT_STRIKETHROUGH, MyFrame::OnUpdateStrikethrough)
428 EVT_UPDATE_UI(ID_FORMAT_SUPERSCRIPT, MyFrame::OnUpdateSuperscript)
429 EVT_UPDATE_UI(ID_FORMAT_SUBSCRIPT, MyFrame::OnUpdateSubscript)
430
5d7836c4
JS
431 EVT_MENU(ID_FORMAT_ALIGN_LEFT, MyFrame::OnAlignLeft)
432 EVT_MENU(ID_FORMAT_ALIGN_CENTRE, MyFrame::OnAlignCentre)
433 EVT_MENU(ID_FORMAT_ALIGN_RIGHT, MyFrame::OnAlignRight)
434
435 EVT_UPDATE_UI(ID_FORMAT_ALIGN_LEFT, MyFrame::OnUpdateAlignLeft)
436 EVT_UPDATE_UI(ID_FORMAT_ALIGN_CENTRE, MyFrame::OnUpdateAlignCentre)
437 EVT_UPDATE_UI(ID_FORMAT_ALIGN_RIGHT, MyFrame::OnUpdateAlignRight)
438
439 EVT_MENU(ID_FORMAT_FONT, MyFrame::OnFont)
cdaed652 440 EVT_MENU(ID_FORMAT_IMAGE, MyFrame::OnImage)
8c9c49a1
JS
441 EVT_MENU(ID_FORMAT_PARAGRAPH, MyFrame::OnParagraph)
442 EVT_MENU(ID_FORMAT_CONTENT, MyFrame::OnFormat)
443 EVT_UPDATE_UI(ID_FORMAT_CONTENT, MyFrame::OnUpdateFormat)
444 EVT_UPDATE_UI(ID_FORMAT_FONT, MyFrame::OnUpdateFormat)
cdaed652 445 EVT_UPDATE_UI(ID_FORMAT_IMAGE, MyFrame::OnUpdateImage)
8c9c49a1 446 EVT_UPDATE_UI(ID_FORMAT_PARAGRAPH, MyFrame::OnUpdateFormat)
5d7836c4
JS
447 EVT_MENU(ID_FORMAT_INDENT_MORE, MyFrame::OnIndentMore)
448 EVT_MENU(ID_FORMAT_INDENT_LESS, MyFrame::OnIndentLess)
449
450 EVT_MENU(ID_FORMAT_LINE_SPACING_HALF, MyFrame::OnLineSpacingHalf)
451 EVT_MENU(ID_FORMAT_LINE_SPACING_SINGLE, MyFrame::OnLineSpacingSingle)
452 EVT_MENU(ID_FORMAT_LINE_SPACING_DOUBLE, MyFrame::OnLineSpacingDouble)
453
454 EVT_MENU(ID_FORMAT_PARAGRAPH_SPACING_MORE, MyFrame::OnParagraphSpacingMore)
455 EVT_MENU(ID_FORMAT_PARAGRAPH_SPACING_LESS, MyFrame::OnParagraphSpacingLess)
456
99404ab0
JS
457 EVT_MENU(ID_RELOAD, MyFrame::OnReload)
458
8c9c49a1 459 EVT_MENU(ID_INSERT_SYMBOL, MyFrame::OnInsertSymbol)
720cc10a 460 EVT_MENU(ID_INSERT_URL, MyFrame::OnInsertURL)
cdaed652 461 EVT_MENU(ID_INSERT_IMAGE, MyFrame::OnInsertImage)
8c9c49a1 462
082cfe55 463 EVT_MENU(ID_FORMAT_NUMBER_LIST, MyFrame::OnNumberList)
e4723634 464 EVT_MENU(ID_FORMAT_BULLETS_AND_NUMBERING, MyFrame::OnBulletsAndNumbering)
082cfe55
JS
465 EVT_MENU(ID_FORMAT_ITEMIZE_LIST, MyFrame::OnItemizeList)
466 EVT_MENU(ID_FORMAT_RENUMBER_LIST, MyFrame::OnRenumberList)
467 EVT_MENU(ID_FORMAT_PROMOTE_LIST, MyFrame::OnPromoteList)
468 EVT_MENU(ID_FORMAT_DEMOTE_LIST, MyFrame::OnDemoteList)
469 EVT_MENU(ID_FORMAT_CLEAR_LIST, MyFrame::OnClearList)
470
f4ac09e8
JS
471 EVT_MENU(ID_TABLE_ADD_COLUMN, MyFrame::OnTableAddColumn)
472 EVT_MENU(ID_TABLE_ADD_ROW, MyFrame::OnTableAddRow)
473 EVT_MENU(ID_TABLE_DELETE_COLUMN, MyFrame::OnTableDeleteColumn)
474 EVT_MENU(ID_TABLE_DELETE_ROW, MyFrame::OnTableDeleteRow)
475 EVT_UPDATE_UI_RANGE(ID_TABLE_ADD_COLUMN, ID_TABLE_ADD_ROW, MyFrame::OnTableFocusedUpdateUI)
476 EVT_UPDATE_UI_RANGE(ID_TABLE_DELETE_COLUMN, ID_TABLE_DELETE_ROW, MyFrame::OnTableHasCellsUpdateUI)
477
5d7836c4 478 EVT_MENU(ID_VIEW_HTML, MyFrame::OnViewHTML)
fe5aa22c 479 EVT_MENU(ID_SWITCH_STYLE_SHEETS, MyFrame::OnSwitchStyleSheets)
e4723634 480 EVT_MENU(ID_MANAGE_STYLES, MyFrame::OnManageStyles)
720cc10a 481
8881d9f0
JS
482 EVT_MENU(ID_PRINT, MyFrame::OnPrint)
483 EVT_MENU(ID_PREVIEW, MyFrame::OnPreview)
484 EVT_MENU(ID_PAGE_SETUP, MyFrame::OnPageSetup)
485
720cc10a
JS
486 EVT_TEXT_URL(wxID_ANY, MyFrame::OnURL)
487 EVT_RICHTEXT_STYLESHEET_REPLACING(wxID_ANY, MyFrame::OnStyleSheetReplacing)
32423dd8
JS
488
489 EVT_MENU(ID_SET_FONT_SCALE, MyFrame::OnSetFontScale)
490 EVT_MENU(ID_SET_DIMENSION_SCALE, MyFrame::OnSetDimensionScale)
5d7836c4
JS
491END_EVENT_TABLE()
492
493// Create a new application object: this macro will allow wxWidgets to create
494// the application object during program execution (it's better than using a
495// static object for many reasons) and also implements the accessor function
496// wxGetApp() which will return the reference of the right type (i.e. MyApp and
497// not wxApp)
498IMPLEMENT_APP(MyApp)
499
500// ============================================================================
501// implementation
502// ============================================================================
503
504// ----------------------------------------------------------------------------
505// the application class
506// ----------------------------------------------------------------------------
507
508// 'Main program' equivalent: the program execution "starts" here
509bool MyApp::OnInit()
510{
45e6e6f8
VZ
511 if ( !wxApp::OnInit() )
512 return false;
513
2569ebc2
JS
514#if wxUSE_HELP
515 wxHelpProvider::Set(new wxSimpleHelpProvider);
516#endif
517
5d7836c4 518 m_styleSheet = new wxRichTextStyleSheet;
8881d9f0
JS
519 m_printing = new wxRichTextPrinting(wxT("Test Document"));
520
521 m_printing->SetFooterText(wxT("@TITLE@"), wxRICHTEXT_PAGE_ALL, wxRICHTEXT_PAGE_CENTRE);
522 m_printing->SetFooterText(wxT("Page @PAGENUM@"), wxRICHTEXT_PAGE_ALL, wxRICHTEXT_PAGE_RIGHT);
5d7836c4
JS
523
524 CreateStyles();
525
cc2aecde
JS
526 MyRichTextCtrl::SetEnhancedDrawingHandler();
527
5d7836c4
JS
528 // Add extra handlers (plain text is automatically added)
529 wxRichTextBuffer::AddHandler(new wxRichTextXMLHandler);
530 wxRichTextBuffer::AddHandler(new wxRichTextHTMLHandler);
531
32423dd8
JS
532 // Add field types
533
534 wxRichTextBuffer::AddFieldType(new wxRichTextFieldTypePropertiesTest(wxT("rectangle"), wxT("RECTANGLE"), wxRichTextFieldTypeStandard::wxRICHTEXT_FIELD_STYLE_RECTANGLE));
535
536 wxRichTextFieldTypeStandard* s1 = new wxRichTextFieldTypeStandard(wxT("begin-section"), wxT("SECTION"), wxRichTextFieldTypeStandard::wxRICHTEXT_FIELD_STYLE_START_TAG);
537 s1->SetBackgroundColour(*wxBLUE);
538
539 wxRichTextFieldTypeStandard* s2 = new wxRichTextFieldTypeStandard(wxT("end-section"), wxT("SECTION"), wxRichTextFieldTypeStandard::wxRICHTEXT_FIELD_STYLE_END_TAG);
540 s2->SetBackgroundColour(*wxBLUE);
541
542 wxRichTextFieldTypeStandard* s3 = new wxRichTextFieldTypeStandard(wxT("bitmap"), wxBitmap(paste_xpm), wxRichTextFieldTypeStandard::wxRICHTEXT_FIELD_STYLE_NO_BORDER);
543
544 wxRichTextBuffer::AddFieldType(s1);
545 wxRichTextBuffer::AddFieldType(s2);
546 wxRichTextBuffer::AddFieldType(s3);
547
548 wxRichTextFieldTypeCompositeTest* s4 = new wxRichTextFieldTypeCompositeTest(wxT("composite"), wxT("This is a field value"));
549 wxRichTextBuffer::AddFieldType(s4);
550
5d7836c4
JS
551 // Add image handlers
552#if wxUSE_LIBPNG
553 wxImage::AddHandler( new wxPNGHandler );
554#endif
9a173d48 555
5d7836c4
JS
556#if wxUSE_LIBJPEG
557 wxImage::AddHandler( new wxJPEGHandler );
558#endif
559
560#if wxUSE_GIF
561 wxImage::AddHandler( new wxGIFHandler );
562#endif
563
720cc10a
JS
564#if wxUSE_FILESYSTEM
565 wxFileSystem::AddHandler( new wxMemoryFSHandler );
566#endif
567
5d7836c4 568 // create the main application window
a640295f
JS
569 wxSize size = wxGetDisplaySize();
570 size.Scale(0.75, 0.75);
571 MyFrame *frame = new MyFrame(wxT("wxRichTextCtrl Sample"), wxID_ANY, wxDefaultPosition, size);
5d7836c4 572
8881d9f0
JS
573 m_printing->SetParentWindow(frame);
574
5d7836c4
JS
575 // and show it (the frames, unlike simple controls, are not shown when
576 // created initially)
577 frame->Show(true);
578
579 // success: wxApp::OnRun() will be called which will enter the main message
580 // loop and the application will run. If we returned false here, the
581 // application would exit immediately.
582 return true;
583}
584
585int MyApp::OnExit()
586{
8881d9f0 587 delete m_printing;
5d7836c4 588 delete m_styleSheet;
8881d9f0 589
5d7836c4
JS
590 return 0;
591}
592
593void MyApp::CreateStyles()
594{
595 // Paragraph styles
596
597 wxFont romanFont(12, wxROMAN, wxNORMAL, wxNORMAL);
598 wxFont swissFont(12, wxSWISS, wxNORMAL, wxNORMAL);
599
600 wxRichTextParagraphStyleDefinition* normalPara = new wxRichTextParagraphStyleDefinition(wxT("Normal"));
601 wxRichTextAttr normalAttr;
602 normalAttr.SetFontFaceName(romanFont.GetFaceName());
603 normalAttr.SetFontSize(12);
604 // Let's set all attributes for this style
605 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|
606 wxTEXT_ATTR_PARA_SPACING_BEFORE|wxTEXT_ATTR_PARA_SPACING_AFTER|wxTEXT_ATTR_LINE_SPACING|
607 wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER);
608 normalPara->SetStyle(normalAttr);
9a173d48 609
5d7836c4
JS
610 m_styleSheet->AddParagraphStyle(normalPara);
611
612 wxRichTextParagraphStyleDefinition* indentedPara = new wxRichTextParagraphStyleDefinition(wxT("Indented"));
613 wxRichTextAttr indentedAttr;
614 indentedAttr.SetFontFaceName(romanFont.GetFaceName());
615 indentedAttr.SetFontSize(12);
616 indentedAttr.SetLeftIndent(100, 0);
617 // We only want to affect indentation
618 indentedAttr.SetFlags(wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT);
619 indentedPara->SetStyle(indentedAttr);
9a173d48 620
5d7836c4
JS
621 m_styleSheet->AddParagraphStyle(indentedPara);
622
27e20452
JS
623 wxRichTextParagraphStyleDefinition* indentedPara2 = new wxRichTextParagraphStyleDefinition(wxT("Red Bold Indented"));
624 wxRichTextAttr indentedAttr2;
625 indentedAttr2.SetFontFaceName(romanFont.GetFaceName());
626 indentedAttr2.SetFontSize(12);
00621a0d 627 indentedAttr2.SetFontWeight(wxFONTWEIGHT_BOLD);
27e20452
JS
628 indentedAttr2.SetTextColour(*wxRED);
629 indentedAttr2.SetFontSize(12);
630 indentedAttr2.SetLeftIndent(100, 0);
631 // We want to affect indentation, font and text colour
632 indentedAttr2.SetFlags(wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT|wxTEXT_ATTR_FONT|wxTEXT_ATTR_TEXT_COLOUR);
633 indentedPara2->SetStyle(indentedAttr2);
634
635 m_styleSheet->AddParagraphStyle(indentedPara2);
636
5d7836c4
JS
637 wxRichTextParagraphStyleDefinition* flIndentedPara = new wxRichTextParagraphStyleDefinition(wxT("First Line Indented"));
638 wxRichTextAttr flIndentedAttr;
639 flIndentedAttr.SetFontFaceName(swissFont.GetFaceName());
640 flIndentedAttr.SetFontSize(12);
641 flIndentedAttr.SetLeftIndent(100, -100);
642 // We only want to affect indentation
643 flIndentedAttr.SetFlags(wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT);
644 flIndentedPara->SetStyle(flIndentedAttr);
9a173d48 645
5d7836c4
JS
646 m_styleSheet->AddParagraphStyle(flIndentedPara);
647
648 // Character styles
649
650 wxRichTextCharacterStyleDefinition* boldDef = new wxRichTextCharacterStyleDefinition(wxT("Bold"));
651 wxRichTextAttr boldAttr;
652 boldAttr.SetFontFaceName(romanFont.GetFaceName());
653 boldAttr.SetFontSize(12);
00621a0d 654 boldAttr.SetFontWeight(wxFONTWEIGHT_BOLD);
5d7836c4
JS
655 // We only want to affect boldness
656 boldAttr.SetFlags(wxTEXT_ATTR_FONT_WEIGHT);
657 boldDef->SetStyle(boldAttr);
9a173d48 658
5d7836c4
JS
659 m_styleSheet->AddCharacterStyle(boldDef);
660
661 wxRichTextCharacterStyleDefinition* italicDef = new wxRichTextCharacterStyleDefinition(wxT("Italic"));
662 wxRichTextAttr italicAttr;
663 italicAttr.SetFontFaceName(romanFont.GetFaceName());
664 italicAttr.SetFontSize(12);
00621a0d 665 italicAttr.SetFontStyle(wxFONTSTYLE_ITALIC);
5d7836c4
JS
666 // We only want to affect italics
667 italicAttr.SetFlags(wxTEXT_ATTR_FONT_ITALIC);
668 italicDef->SetStyle(italicAttr);
9a173d48 669
5d7836c4
JS
670 m_styleSheet->AddCharacterStyle(italicDef);
671
672 wxRichTextCharacterStyleDefinition* redDef = new wxRichTextCharacterStyleDefinition(wxT("Red Bold"));
673 wxRichTextAttr redAttr;
674 redAttr.SetFontFaceName(romanFont.GetFaceName());
675 redAttr.SetFontSize(12);
00621a0d 676 redAttr.SetFontWeight(wxFONTWEIGHT_BOLD);
5d7836c4
JS
677 redAttr.SetTextColour(*wxRED);
678 // We only want to affect colour, weight and face
679 redAttr.SetFlags(wxTEXT_ATTR_FONT_FACE|wxTEXT_ATTR_FONT_WEIGHT|wxTEXT_ATTR_TEXT_COLOUR);
680 redDef->SetStyle(redAttr);
9a173d48 681
5d7836c4 682 m_styleSheet->AddCharacterStyle(redDef);
082cfe55
JS
683
684 wxRichTextListStyleDefinition* bulletList = new wxRichTextListStyleDefinition(wxT("Bullet List 1"));
685 int i;
686 for (i = 0; i < 10; i++)
687 {
720cc10a 688 wxString bulletText;
082cfe55 689 if (i == 0)
720cc10a 690 bulletText = wxT("standard/circle");
082cfe55 691 else if (i == 1)
720cc10a 692 bulletText = wxT("standard/square");
082cfe55 693 else if (i == 2)
720cc10a 694 bulletText = wxT("standard/circle");
082cfe55 695 else if (i == 3)
720cc10a 696 bulletText = wxT("standard/square");
082cfe55 697 else
720cc10a 698 bulletText = wxT("standard/circle");
082cfe55 699
720cc10a 700 bulletList->SetAttributes(i, (i+1)*60, 60, wxTEXT_ATTR_BULLET_STYLE_STANDARD, bulletText);
082cfe55
JS
701 }
702
703 m_styleSheet->AddListStyle(bulletList);
704
705 wxRichTextListStyleDefinition* numberedList = new wxRichTextListStyleDefinition(wxT("Numbered List 1"));
706 for (i = 0; i < 10; i++)
707 {
708 long numberStyle;
709 if (i == 0)
710 numberStyle = wxTEXT_ATTR_BULLET_STYLE_ARABIC|wxTEXT_ATTR_BULLET_STYLE_PERIOD;
711 else if (i == 1)
712 numberStyle = wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER|wxTEXT_ATTR_BULLET_STYLE_PARENTHESES;
713 else if (i == 2)
714 numberStyle = wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER|wxTEXT_ATTR_BULLET_STYLE_PARENTHESES;
715 else if (i == 3)
716 numberStyle = wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER|wxTEXT_ATTR_BULLET_STYLE_PARENTHESES;
717 else
718 numberStyle = wxTEXT_ATTR_BULLET_STYLE_ARABIC|wxTEXT_ATTR_BULLET_STYLE_PERIOD;
719
720cc10a
JS
720 numberStyle |= wxTEXT_ATTR_BULLET_STYLE_ALIGN_RIGHT;
721
082cfe55
JS
722 numberedList->SetAttributes(i, (i+1)*60, 60, numberStyle);
723 }
724
725 m_styleSheet->AddListStyle(numberedList);
720cc10a
JS
726
727 wxRichTextListStyleDefinition* outlineList = new wxRichTextListStyleDefinition(wxT("Outline List 1"));
728 for (i = 0; i < 10; i++)
729 {
730 long numberStyle;
731 if (i < 4)
732 numberStyle = wxTEXT_ATTR_BULLET_STYLE_OUTLINE|wxTEXT_ATTR_BULLET_STYLE_PERIOD;
733 else
734 numberStyle = wxTEXT_ATTR_BULLET_STYLE_ARABIC|wxTEXT_ATTR_BULLET_STYLE_PERIOD;
735
736 outlineList->SetAttributes(i, (i+1)*120, 120, numberStyle);
737 }
738
739 m_styleSheet->AddListStyle(outlineList);
5d7836c4
JS
740}
741
742// ----------------------------------------------------------------------------
743// main frame
744// ----------------------------------------------------------------------------
745
746// frame constructor
747MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
748 const wxSize& size, long style)
749 : wxFrame(NULL, id, title, pos, size, style)
750{
b4e415df
JS
751#ifdef __WXMAC__
752 SetWindowVariant(wxWINDOW_VARIANT_SMALL);
753#endif
754
5d7836c4 755 // set the frame icon
1226b3b3 756 SetIcon(wxICON(sample));
5d7836c4
JS
757
758 // create a menu bar
759 wxMenu *fileMenu = new wxMenu;
760
761 // the "About" item should be in the help menu
762 wxMenu *helpMenu = new wxMenu;
2d143b66 763 helpMenu->Append(ID_About, wxT("&About\tF1"), wxT("Show about dialog"));
5d7836c4 764
9a83f860
VZ
765 fileMenu->Append(wxID_OPEN, wxT("&Open\tCtrl+O"), wxT("Open a file"));
766 fileMenu->Append(wxID_SAVE, wxT("&Save\tCtrl+S"), wxT("Save a file"));
767 fileMenu->Append(wxID_SAVEAS, wxT("&Save As...\tF12"), wxT("Save to a new file"));
5d7836c4 768 fileMenu->AppendSeparator();
9a83f860 769 fileMenu->Append(ID_RELOAD, wxT("&Reload Text\tF2"), wxT("Reload the initial text"));
99404ab0 770 fileMenu->AppendSeparator();
9a83f860
VZ
771 fileMenu->Append(ID_PAGE_SETUP, wxT("Page Set&up..."), wxT("Page setup"));
772 fileMenu->Append(ID_PRINT, wxT("&Print...\tCtrl+P"), wxT("Print"));
773 fileMenu->Append(ID_PREVIEW, wxT("Print Pre&view"), wxT("Print preview"));
8881d9f0 774 fileMenu->AppendSeparator();
9a83f860 775 fileMenu->Append(ID_VIEW_HTML, wxT("&View as HTML"), wxT("View HTML"));
5d7836c4 776 fileMenu->AppendSeparator();
9a83f860 777 fileMenu->Append(ID_Quit, wxT("E&xit\tAlt+X"), wxT("Quit this program"));
5d7836c4
JS
778
779 wxMenu* editMenu = new wxMenu;
780 editMenu->Append(wxID_UNDO, _("&Undo\tCtrl+Z"));
781 editMenu->Append(wxID_REDO, _("&Redo\tCtrl+Y"));
782 editMenu->AppendSeparator();
783 editMenu->Append(wxID_CUT, _("Cu&t\tCtrl+X"));
784 editMenu->Append(wxID_COPY, _("&Copy\tCtrl+C"));
785 editMenu->Append(wxID_PASTE, _("&Paste\tCtrl+V"));
786
5d7836c4
JS
787 editMenu->AppendSeparator();
788 editMenu->Append(wxID_SELECTALL, _("Select A&ll\tCtrl+A"));
5d7836c4 789 editMenu->AppendSeparator();
32423dd8
JS
790 editMenu->Append(ID_SET_FONT_SCALE, _("Set &Text Scale..."));
791 editMenu->Append(ID_SET_DIMENSION_SCALE, _("Set &Dimension Scale..."));
5d7836c4
JS
792
793 wxMenu* formatMenu = new wxMenu;
794 formatMenu->AppendCheckItem(ID_FORMAT_BOLD, _("&Bold\tCtrl+B"));
795 formatMenu->AppendCheckItem(ID_FORMAT_ITALIC, _("&Italic\tCtrl+I"));
796 formatMenu->AppendCheckItem(ID_FORMAT_UNDERLINE, _("&Underline\tCtrl+U"));
797 formatMenu->AppendSeparator();
75936ec6
JS
798 formatMenu->AppendCheckItem(ID_FORMAT_STRIKETHROUGH, _("Stri&kethrough"));
799 formatMenu->AppendCheckItem(ID_FORMAT_SUPERSCRIPT, _("Superscrip&t"));
800 formatMenu->AppendCheckItem(ID_FORMAT_SUBSCRIPT, _("Subscrip&t"));
801 formatMenu->AppendSeparator();
5d7836c4
JS
802 formatMenu->AppendCheckItem(ID_FORMAT_ALIGN_LEFT, _("L&eft Align"));
803 formatMenu->AppendCheckItem(ID_FORMAT_ALIGN_RIGHT, _("&Right Align"));
804 formatMenu->AppendCheckItem(ID_FORMAT_ALIGN_CENTRE, _("&Centre"));
805 formatMenu->AppendSeparator();
c4cd20cf 806 formatMenu->Append(ID_FORMAT_INDENT_MORE, _("Indent &More"));
5d7836c4
JS
807 formatMenu->Append(ID_FORMAT_INDENT_LESS, _("Indent &Less"));
808 formatMenu->AppendSeparator();
809 formatMenu->Append(ID_FORMAT_PARAGRAPH_SPACING_MORE, _("Increase Paragraph &Spacing"));
810 formatMenu->Append(ID_FORMAT_PARAGRAPH_SPACING_LESS, _("Decrease &Paragraph Spacing"));
811 formatMenu->AppendSeparator();
812 formatMenu->Append(ID_FORMAT_LINE_SPACING_SINGLE, _("Normal Line Spacing"));
813 formatMenu->Append(ID_FORMAT_LINE_SPACING_HALF, _("1.5 Line Spacing"));
814 formatMenu->Append(ID_FORMAT_LINE_SPACING_DOUBLE, _("Double Line Spacing"));
815 formatMenu->AppendSeparator();
816 formatMenu->Append(ID_FORMAT_FONT, _("&Font..."));
cdaed652 817 formatMenu->Append(ID_FORMAT_IMAGE, _("Image Property"));
8c9c49a1
JS
818 formatMenu->Append(ID_FORMAT_PARAGRAPH, _("&Paragraph..."));
819 formatMenu->Append(ID_FORMAT_CONTENT, _("Font and Pa&ragraph...\tShift+Ctrl+F"));
fe5aa22c
JS
820 formatMenu->AppendSeparator();
821 formatMenu->Append(ID_SWITCH_STYLE_SHEETS, _("&Switch Style Sheets"));
e4723634
JS
822 formatMenu->Append(ID_MANAGE_STYLES, _("&Manage Styles"));
823
824 wxMenu* listsMenu = new wxMenu;
825 listsMenu->Append(ID_FORMAT_BULLETS_AND_NUMBERING, _("Bullets and &Numbering..."));
826 listsMenu->AppendSeparator();
827 listsMenu->Append(ID_FORMAT_NUMBER_LIST, _("Number List"));
828 listsMenu->Append(ID_FORMAT_ITEMIZE_LIST, _("Itemize List"));
829 listsMenu->Append(ID_FORMAT_RENUMBER_LIST, _("Renumber List"));
830 listsMenu->Append(ID_FORMAT_PROMOTE_LIST, _("Promote List Items"));
831 listsMenu->Append(ID_FORMAT_DEMOTE_LIST, _("Demote List Items"));
832 listsMenu->Append(ID_FORMAT_CLEAR_LIST, _("Clear List Formatting"));
5d7836c4 833
f4ac09e8
JS
834 wxMenu* tableMenu = new wxMenu;
835 tableMenu->Append(ID_TABLE_ADD_COLUMN, _("&Add Column"));
836 tableMenu->Append(ID_TABLE_ADD_ROW, _("Add &Row"));
837 tableMenu->Append(ID_TABLE_DELETE_COLUMN, _("Delete &Column"));
838 tableMenu->Append(ID_TABLE_DELETE_ROW, _("&Delete Row"));
839
8c9c49a1
JS
840 wxMenu* insertMenu = new wxMenu;
841 insertMenu->Append(ID_INSERT_SYMBOL, _("&Symbol...\tCtrl+I"));
720cc10a 842 insertMenu->Append(ID_INSERT_URL, _("&URL..."));
cdaed652 843 insertMenu->Append(ID_INSERT_IMAGE, _("&Image..."));
8c9c49a1 844
5d7836c4
JS
845 // now append the freshly created menu to the menu bar...
846 wxMenuBar *menuBar = new wxMenuBar();
9a83f860
VZ
847 menuBar->Append(fileMenu, wxT("&File"));
848 menuBar->Append(editMenu, wxT("&Edit"));
849 menuBar->Append(formatMenu, wxT("F&ormat"));
850 menuBar->Append(listsMenu, wxT("&Lists"));
f4ac09e8 851 menuBar->Append(tableMenu, wxT("&Tables"));
9a83f860
VZ
852 menuBar->Append(insertMenu, wxT("&Insert"));
853 menuBar->Append(helpMenu, wxT("&Help"));
5d7836c4
JS
854
855 // ... and attach this menu bar to the frame
856 SetMenuBar(menuBar);
857
858 // create a status bar just for fun (by default with 1 pane only)
4753c7ce
WS
859 // but don't create it on limited screen space (WinCE)
860 bool is_pda = wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA;
861
9a173d48 862#if wxUSE_STATUSBAR
4753c7ce
WS
863 if ( !is_pda )
864 {
865 CreateStatusBar(2);
9a83f860 866 SetStatusText(wxT("Welcome to wxRichTextCtrl!"));
4753c7ce 867 }
9a173d48 868#endif
5d7836c4 869
b4e415df
JS
870 wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
871 SetSizer(sizer);
872
873 // On Mac, don't create a 'native' wxToolBar because small bitmaps are not supported by native
874 // toolbars. On Mac, a non-native, small-bitmap toolbar doesn't show unless it is explicitly
875 // managed, hence the use of sizers. In a real application, use larger icons for the main
876 // toolbar to avoid the need for this workaround. Or, use the toolbar in a container window
877 // as part of a more complex hierarchy, and the toolbar will automatically be non-native.
878
879 wxSystemOptions::SetOption(wxT("mac.toolbar.no-native"), 1);
880
881 wxToolBar* toolBar = new wxToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
882 wxNO_BORDER|wxTB_FLAT|wxTB_NODIVIDER|wxTB_NOALIGN);
883
884 sizer->Add(toolBar, 0, wxEXPAND);
5d7836c4 885
bbe28fbb
PC
886 toolBar->AddTool(wxID_OPEN, wxEmptyString, wxBitmap(open_xpm), _("Open"));
887 toolBar->AddTool(wxID_SAVEAS, wxEmptyString, wxBitmap(save_xpm), _("Save"));
5d7836c4 888 toolBar->AddSeparator();
bbe28fbb
PC
889 toolBar->AddTool(wxID_CUT, wxEmptyString, wxBitmap(cut_xpm), _("Cut"));
890 toolBar->AddTool(wxID_COPY, wxEmptyString, wxBitmap(copy_xpm), _("Copy"));
891 toolBar->AddTool(wxID_PASTE, wxEmptyString, wxBitmap(paste_xpm), _("Paste"));
5d7836c4 892 toolBar->AddSeparator();
bbe28fbb
PC
893 toolBar->AddTool(wxID_UNDO, wxEmptyString, wxBitmap(undo_xpm), _("Undo"));
894 toolBar->AddTool(wxID_REDO, wxEmptyString, wxBitmap(redo_xpm), _("Redo"));
5d7836c4 895 toolBar->AddSeparator();
bbe28fbb
PC
896 toolBar->AddCheckTool(ID_FORMAT_BOLD, wxEmptyString, wxBitmap(bold_xpm), wxNullBitmap, _("Bold"));
897 toolBar->AddCheckTool(ID_FORMAT_ITALIC, wxEmptyString, wxBitmap(italic_xpm), wxNullBitmap, _("Italic"));
898 toolBar->AddCheckTool(ID_FORMAT_UNDERLINE, wxEmptyString, wxBitmap(underline_xpm), wxNullBitmap, _("Underline"));
5d7836c4 899 toolBar->AddSeparator();
bbe28fbb
PC
900 toolBar->AddCheckTool(ID_FORMAT_ALIGN_LEFT, wxEmptyString, wxBitmap(alignleft_xpm), wxNullBitmap, _("Align Left"));
901 toolBar->AddCheckTool(ID_FORMAT_ALIGN_CENTRE, wxEmptyString, wxBitmap(centre_xpm), wxNullBitmap, _("Centre"));
902 toolBar->AddCheckTool(ID_FORMAT_ALIGN_RIGHT, wxEmptyString, wxBitmap(alignright_xpm), wxNullBitmap, _("Align Right"));
5d7836c4 903 toolBar->AddSeparator();
bbe28fbb
PC
904 toolBar->AddTool(ID_FORMAT_INDENT_LESS, wxEmptyString, wxBitmap(indentless_xpm), _("Indent Less"));
905 toolBar->AddTool(ID_FORMAT_INDENT_MORE, wxEmptyString, wxBitmap(indentmore_xpm), _("Indent More"));
5d7836c4 906 toolBar->AddSeparator();
bbe28fbb 907 toolBar->AddTool(ID_FORMAT_FONT, wxEmptyString, wxBitmap(font_xpm), _("Font"));
b4e415df 908 toolBar->AddSeparator();
5d7836c4 909
b4e415df 910 wxRichTextStyleComboCtrl* combo = new wxRichTextStyleComboCtrl(toolBar, ID_RICHTEXT_STYLE_COMBO, wxDefaultPosition, wxSize(160, -1), wxCB_READONLY);
e637208a
JS
911 toolBar->AddControl(combo);
912
5d7836c4
JS
913 toolBar->Realize();
914
a640295f 915 wxSplitterWindow* splitter = new wxSplitterWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_LIVE_UPDATE);
b4e415df 916 sizer->Add(splitter, 1, wxEXPAND);
5d7836c4
JS
917
918 wxFont textFont = wxFont(12, wxROMAN, wxNORMAL, wxNORMAL);
919 wxFont boldFont = wxFont(12, wxROMAN, wxNORMAL, wxBOLD);
920 wxFont italicFont = wxFont(12, wxROMAN, wxITALIC, wxNORMAL);
921
a640295f 922 m_richTextCtrl = new MyRichTextCtrl(splitter, ID_RICHTEXT_CTRL, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxVSCROLL|wxHSCROLL|wxWANTS_CHARS);
32423dd8
JS
923 wxASSERT(!m_richTextCtrl->GetBuffer().GetAttributes().HasFontPixelSize());
924
ff2baa25
JS
925 wxFont font(12, wxROMAN, wxNORMAL, wxNORMAL);
926
ff2baa25 927 m_richTextCtrl->SetFont(font);
5d7836c4 928
32423dd8
JS
929 wxASSERT(!m_richTextCtrl->GetBuffer().GetAttributes().HasFontPixelSize());
930
603f702b
JS
931 m_richTextCtrl->SetMargins(10, 10);
932
fe5aa22c
JS
933 m_richTextCtrl->SetStyleSheet(wxGetApp().GetStyleSheet());
934
e637208a
JS
935 combo->SetStyleSheet(wxGetApp().GetStyleSheet());
936 combo->SetRichTextCtrl(m_richTextCtrl);
937 combo->UpdateStyles();
938
082cfe55 939 wxRichTextStyleListCtrl* styleListCtrl = new wxRichTextStyleListCtrl(splitter, ID_RICHTEXT_STYLE_LIST);
4753c7ce
WS
940
941 wxSize display = wxGetDisplaySize();
942 if ( is_pda && ( display.GetWidth() < display.GetHeight() ) )
943 {
082cfe55 944 splitter->SplitHorizontally(m_richTextCtrl, styleListCtrl);
4753c7ce
WS
945 }
946 else
947 {
a640295f
JS
948 int width = GetClientSize().GetWidth() * 0.8;
949 splitter->SplitVertically(m_richTextCtrl, styleListCtrl, width);
950 splitter->SetSashGravity(0.8);
4753c7ce 951 }
5d7836c4 952
b4e415df
JS
953 Layout();
954
c59f6793
JS
955 splitter->UpdateSize();
956
082cfe55
JS
957 styleListCtrl->SetStyleSheet(wxGetApp().GetStyleSheet());
958 styleListCtrl->SetRichTextCtrl(m_richTextCtrl);
959 styleListCtrl->UpdateStyles();
5d7836c4 960
99404ab0
JS
961 WriteInitialText();
962}
963
964// Write text
965void MyFrame::WriteInitialText()
966{
cc2aecde 967 MyRichTextCtrl& r = *m_richTextCtrl;
5d7836c4 968
99404ab0
JS
969 r.SetDefaultStyle(wxRichTextAttr());
970
b4e415df 971 r.Freeze();
cc2aecde 972
5d7836c4
JS
973 r.BeginSuppressUndo();
974
975 r.BeginParagraphSpacing(0, 20);
976
977 r.BeginAlignment(wxTEXT_ALIGNMENT_CENTRE);
978 r.BeginBold();
979
980 r.BeginFontSize(14);
c3e54dee 981
50f65288 982 wxString lineBreak = (wxChar) 29;
c3e54dee 983
99404ab0 984 r.WriteText(wxString(wxT("Welcome to wxRichTextCtrl, a wxWidgets control")) + lineBreak + wxT("for editing and presenting styled text and images\n"));
5d7836c4 985 r.EndFontSize();
5d7836c4
JS
986
987 r.BeginItalic();
988 r.WriteText(wxT("by Julian Smart"));
989 r.EndItalic();
990
991 r.EndBold();
5d7836c4 992 r.Newline();
42688aea 993
5d7836c4
JS
994 r.WriteImage(wxBitmap(zebra_xpm));
995
5d7836c4
JS
996 r.Newline();
997 r.Newline();
998
99404ab0
JS
999 r.EndAlignment();
1000
32423dd8
JS
1001#if 0
1002 r.BeginAlignment(wxTEXT_ALIGNMENT_CENTRE);
1003 r.WriteText(wxString(wxT("This is a simple test for a floating left image test. The zebra image should be placed at the left side of the current buffer and all the text should flow around it at the right side. This is a simple test for a floating left image test. The zebra image should be placed at the left side of the current buffer and all the text should flow around it at the right side. This is a simple test for a floating left image test. The zebra image should be placed at the left side of the current buffer and all the text should flow around it at the right side.")));
1004 r.Newline();
1005 r.EndAlignment();
1006#endif
1007
cdaed652 1008 r.BeginAlignment(wxTEXT_ALIGNMENT_LEFT);
24777478
JS
1009 wxRichTextAttr imageAttr;
1010 imageAttr.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_LEFT);
cdaed652 1011 r.WriteText(wxString(wxT("This is a simple test for a floating left image test. The zebra image should be placed at the left side of the current buffer and all the text should flow around it at the right side. This is a simple test for a floating left image test. The zebra image should be placed at the left side of the current buffer and all the text should flow around it at the right side. This is a simple test for a floating left image test. The zebra image should be placed at the left side of the current buffer and all the text should flow around it at the right side.")));
24777478 1012 r.WriteImage(wxBitmap(zebra_xpm), wxBITMAP_TYPE_PNG, imageAttr);
75936ec6 1013
24777478
JS
1014 imageAttr.GetTextBoxAttr().GetTop().SetValue(200);
1015 imageAttr.GetTextBoxAttr().GetTop().SetUnits(wxTEXT_ATTR_UNITS_PIXELS);
1016 imageAttr.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_RIGHT);
1017 r.WriteImage(wxBitmap(zebra_xpm), wxBITMAP_TYPE_PNG, imageAttr);
5ad9ae3a 1018 r.WriteText(wxString(wxT("This is a simple test for a floating right image test. The zebra image should be placed at the right side of the current buffer and all the text should flow around it at the left side. This is a simple test for a floating left image test. The zebra image should be placed at the right side of the current buffer and all the text should flow around it at the left side. This is a simple test for a floating left image test. The zebra image should be placed at the right side of the current buffer and all the text should flow around it at the left side.")));
cdaed652
VZ
1019 r.EndAlignment();
1020 r.Newline();
1021
5d7836c4 1022 r.WriteText(wxT("What can you do with this thing? "));
42688aea 1023
5d7836c4
JS
1024 r.WriteImage(wxBitmap(smiley_xpm));
1025 r.WriteText(wxT(" Well, you can change text "));
1026
ea92bb67 1027 r.BeginTextColour(*wxRED);
5d7836c4
JS
1028 r.WriteText(wxT("colour, like this red bit."));
1029 r.EndTextColour();
1030
3e541562
JS
1031 wxRichTextAttr backgroundColourAttr;
1032 backgroundColourAttr.SetBackgroundColour(*wxGREEN);
ea92bb67 1033 backgroundColourAttr.SetTextColour(*wxBLUE);
3e541562
JS
1034 r.BeginStyle(backgroundColourAttr);
1035 r.WriteText(wxT(" And this blue on green bit."));
1036 r.EndStyle();
5d7836c4
JS
1037
1038 r.WriteText(wxT(" Naturally you can make things "));
1039 r.BeginBold();
1040 r.WriteText(wxT("bold "));
1041 r.EndBold();
1042 r.BeginItalic();
1043 r.WriteText(wxT("or italic "));
1044 r.EndItalic();
1045 r.BeginUnderline();
1046 r.WriteText(wxT("or underlined."));
1047 r.EndUnderline();
1048
1049 r.BeginFontSize(14);
1050 r.WriteText(wxT(" Different font sizes on the same line is allowed, too."));
1051 r.EndFontSize();
1052
1053 r.WriteText(wxT(" Next we'll show an indented paragraph."));
1054
5d7836c4
JS
1055 r.Newline();
1056
99404ab0 1057 r.BeginLeftIndent(60);
5d7836c4 1058 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."));
5d7836c4
JS
1059 r.Newline();
1060
99404ab0
JS
1061 r.EndLeftIndent();
1062
5d7836c4
JS
1063 r.WriteText(wxT("Next, we'll show a first-line indent, achieved using BeginLeftIndent(100, -40)."));
1064
5d7836c4
JS
1065 r.Newline();
1066
99404ab0 1067 r.BeginLeftIndent(100, -40);
5d7836c4 1068
99404ab0 1069 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."));
5d7836c4
JS
1070 r.Newline();
1071
99404ab0 1072 r.EndLeftIndent();
5d7836c4 1073
99404ab0 1074 r.WriteText(wxT("Numbered bullets are possible, again using subindents:"));
5d7836c4
JS
1075 r.Newline();
1076
99404ab0 1077 r.BeginNumberedBullet(1, 100, 60);
082cfe55 1078 r.WriteText(wxT("This is my first item. Note that wxRichTextCtrl can apply numbering and bullets automatically based on list styles, but this list is formatted explicitly by setting indents."));
99404ab0 1079 r.Newline();
5d7836c4
JS
1080 r.EndNumberedBullet();
1081
1082 r.BeginNumberedBullet(2, 100, 60);
5d7836c4 1083 r.WriteText(wxT("This is my second item."));
5d7836c4 1084 r.Newline();
99404ab0 1085 r.EndNumberedBullet();
5d7836c4
JS
1086
1087 r.WriteText(wxT("The following paragraph is right-indented:"));
99404ab0 1088 r.Newline();
5d7836c4
JS
1089
1090 r.BeginRightIndent(200);
5d7836c4
JS
1091
1092 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."));
5d7836c4
JS
1093 r.Newline();
1094
99404ab0
JS
1095 r.EndRightIndent();
1096
5d7836c4 1097 r.WriteText(wxT("The following paragraph is right-aligned with 1.5 line spacing:"));
99404ab0 1098 r.Newline();
5d7836c4
JS
1099
1100 r.BeginAlignment(wxTEXT_ALIGNMENT_RIGHT);
1101 r.BeginLineSpacing(wxTEXT_ATTR_LINE_SPACING_HALF);
5d7836c4 1102 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."));
99404ab0 1103 r.Newline();
5d7836c4
JS
1104 r.EndLineSpacing();
1105 r.EndAlignment();
1106
7f0d9d71
JS
1107 wxArrayInt tabs;
1108 tabs.Add(400);
1109 tabs.Add(600);
1110 tabs.Add(800);
1111 tabs.Add(1000);
24777478 1112 wxRichTextAttr attr;
7f0d9d71
JS
1113 attr.SetFlags(wxTEXT_ATTR_TABS);
1114 attr.SetTabs(tabs);
1115 r.SetDefaultStyle(attr);
4753c7ce 1116
7f0d9d71 1117 r.WriteText(wxT("This line contains tabs:\tFirst tab\tSecond tab\tThird tab"));
5d7836c4 1118 r.Newline();
99404ab0 1119
5d7836c4 1120 r.WriteText(wxT("Other notable features of wxRichTextCtrl include:"));
99404ab0 1121 r.Newline();
5d7836c4
JS
1122
1123 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 1124 r.WriteText(wxT("Compatibility with wxTextCtrl API"));
99404ab0 1125 r.Newline();
5d7836c4
JS
1126 r.EndSymbolBullet();
1127
1128 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 1129 r.WriteText(wxT("Easy stack-based BeginXXX()...EndXXX() style setting in addition to SetStyle()"));
99404ab0 1130 r.Newline();
5d7836c4
JS
1131 r.EndSymbolBullet();
1132
1133 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 1134 r.WriteText(wxT("XML loading and saving"));
99404ab0 1135 r.Newline();
5d7836c4
JS
1136 r.EndSymbolBullet();
1137
1138 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 1139 r.WriteText(wxT("Undo/Redo, with batching option and Undo suppressing"));
99404ab0 1140 r.Newline();
5d7836c4
JS
1141 r.EndSymbolBullet();
1142
1143 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 1144 r.WriteText(wxT("Clipboard copy and paste"));
99404ab0 1145 r.Newline();
5d7836c4
JS
1146 r.EndSymbolBullet();
1147
1148 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 1149 r.WriteText(wxT("wxRichTextStyleSheet with named character and paragraph styles, and control for applying named styles"));
99404ab0 1150 r.Newline();
5d7836c4
JS
1151 r.EndSymbolBullet();
1152
1153 r.BeginSymbolBullet(wxT('*'), 100, 60);
5d7836c4 1154 r.WriteText(wxT("A design that can easily be extended to other content types, ultimately with text boxes, tables, controls, and so on"));
5d7836c4 1155 r.Newline();
99404ab0 1156 r.EndSymbolBullet();
5d7836c4 1157
720cc10a
JS
1158 // Make a style suitable for showing a URL
1159 wxRichTextAttr urlStyle;
1160 urlStyle.SetTextColour(*wxBLUE);
1161 urlStyle.SetFontUnderlined(true);
1162
1163 r.WriteText(wxT("wxRichTextCtrl can also display URLs, such as this one: "));
1164 r.BeginStyle(urlStyle);
1165 r.BeginURL(wxT("http://www.wxwidgets.org"));
1166 r.WriteText(wxT("The wxWidgets Web Site"));
1167 r.EndURL();
1168 r.EndStyle();
1169 r.WriteText(wxT(". Click on the URL to generate an event."));
1170
1171 r.Newline();
1172
99404ab0 1173 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!\n"));
5d7836c4
JS
1174
1175 r.EndParagraphSpacing();
603f702b 1176
32423dd8 1177#if 1
603f702b
JS
1178 {
1179 // Add a text box
1180
1181 r.Newline();
75936ec6 1182
603f702b
JS
1183 wxRichTextAttr attr;
1184 attr.GetTextBoxAttr().GetMargins().GetLeft().SetValue(20, wxTEXT_ATTR_UNITS_PIXELS);
1185 attr.GetTextBoxAttr().GetMargins().GetTop().SetValue(20, wxTEXT_ATTR_UNITS_PIXELS);
1186 attr.GetTextBoxAttr().GetMargins().GetRight().SetValue(20, wxTEXT_ATTR_UNITS_PIXELS);
1187 attr.GetTextBoxAttr().GetMargins().GetBottom().SetValue(20, wxTEXT_ATTR_UNITS_PIXELS);
5d7836c4 1188
603f702b
JS
1189 attr.GetTextBoxAttr().GetBorder().SetColour(*wxBLACK);
1190 attr.GetTextBoxAttr().GetBorder().SetWidth(1, wxTEXT_ATTR_UNITS_PIXELS);
1191 attr.GetTextBoxAttr().GetBorder().SetStyle(wxTEXT_BOX_ATTR_BORDER_SOLID);
1192
1193 wxRichTextBox* textBox = r.WriteTextBox(attr);
1194 r.SetFocusObject(textBox);
1195
1196 r.WriteText(wxT("This is a text box. Just testing! Once more unto the breach, dear friends, once more..."));
1197
1198 r.SetFocusObject(NULL); // Set the focus back to the main buffer
1199 r.SetInsertionPointEnd();
1200 }
1201#endif
f4ac09e8 1202
603f702b
JS
1203#if 1
1204 {
1205 // Add a table
1206
1207 r.Newline();
75936ec6 1208
603f702b
JS
1209 wxRichTextAttr attr;
1210 attr.GetTextBoxAttr().GetMargins().GetLeft().SetValue(5, wxTEXT_ATTR_UNITS_PIXELS);
1211 attr.GetTextBoxAttr().GetMargins().GetTop().SetValue(5, wxTEXT_ATTR_UNITS_PIXELS);
1212 attr.GetTextBoxAttr().GetMargins().GetRight().SetValue(5, wxTEXT_ATTR_UNITS_PIXELS);
1213 attr.GetTextBoxAttr().GetMargins().GetBottom().SetValue(5, wxTEXT_ATTR_UNITS_PIXELS);
1214 attr.GetTextBoxAttr().GetPadding() = attr.GetTextBoxAttr().GetMargins();
1215
1216 attr.GetTextBoxAttr().GetBorder().SetColour(*wxBLACK);
1217 attr.GetTextBoxAttr().GetBorder().SetWidth(1, wxTEXT_ATTR_UNITS_PIXELS);
1218 attr.GetTextBoxAttr().GetBorder().SetStyle(wxTEXT_BOX_ATTR_BORDER_SOLID);
1219
1220 wxRichTextAttr cellAttr = attr;
1221 cellAttr.GetTextBoxAttr().GetWidth().SetValue(200, wxTEXT_ATTR_UNITS_PIXELS);
1222 cellAttr.GetTextBoxAttr().GetHeight().SetValue(150, wxTEXT_ATTR_UNITS_PIXELS);
1223
a640295f
JS
1224 wxRichTextTable* table = r.WriteTable(6, 4, attr, cellAttr);
1225
603f702b
JS
1226 int i, j;
1227 for (j = 0; j < table->GetRowCount(); j++)
1228 {
1229 for (i = 0; i < table->GetColumnCount(); i++)
1230 {
1231 wxString msg = wxString::Format(wxT("This is cell %d, %d"), (j+1), (i+1));
1232 r.SetFocusObject(table->GetCell(j, i));
1233 r.WriteText(msg);
1234 }
1235 }
a640295f
JS
1236
1237 // Demonstrate colspan and rowspan
1238 wxRichTextCell* cell = table->GetCell(1, 0);
1239 cell->SetColspan(2);
1240 r.SetFocusObject(cell);
1241 cell->Clear();
1242 r.WriteText("This cell spans 2 columns");
1243
1244 cell = table->GetCell(1, 3);
1245 cell->SetRowspan(2);
1246 r.SetFocusObject(cell);
1247 cell->Clear();
1248 r.WriteText("This cell spans 2 rows");
1249
1250 cell = table->GetCell(2, 1);
1251 cell->SetColspan(2);
1252 cell->SetRowspan(3);
1253 r.SetFocusObject(cell);
1254 cell->Clear();
1255 r.WriteText("This cell spans 2 columns and 3 rows");
f4ac09e8 1256
603f702b
JS
1257 r.SetFocusObject(NULL); // Set the focus back to the main buffer
1258 r.SetInsertionPointEnd();
1259 }
1260#endif
75936ec6 1261
a640295f 1262 r.Newline(); r.Newline();
32423dd8
JS
1263
1264 wxRichTextProperties properties;
1265 r.WriteText(wxT("This is a rectangle field: "));
1266 r.WriteField(wxT("rectangle"), properties);
1267 r.WriteText(wxT(" and a begin section field: "));
1268 r.WriteField(wxT("begin-section"), properties);
1269 r.WriteText(wxT("This is text between the two tags."));
1270 r.WriteField(wxT("end-section"), properties);
1271 r.WriteText(wxT(" Now a bitmap. "));
1272 r.WriteField(wxT("bitmap"), properties);
1273 r.WriteText(wxT(" Before we go, here's a composite field: ***"));
1274 wxRichTextField* field = r.WriteField(wxT("composite"), properties);
1275 field->UpdateField(& r.GetBuffer()); // Creates the composite value (sort of a text box)
1276 r.WriteText(wxT("*** End of composite field."));
1277
1278 r.Newline();
5d7836c4 1279 r.EndSuppressUndo();
b4e415df
JS
1280
1281 // Add some locked content first - needs Undo to be enabled
1282 {
1283 r.BeginLock();
1284 r.WriteText(wxString(wxT("This is a locked object.")));
1285 r.EndLock();
1286
1287 r.WriteText(wxString(wxT(" This is unlocked text. ")));
1288
1289 r.BeginLock();
1290 r.WriteText(wxString(wxT("More locked content.")));
1291 r.EndLock();
1292 r.Newline();
1293
1294 // Flush the Undo buffer
1295 r.GetCommandProcessor()->ClearCommands();
1296 }
1297
1298 r.Thaw();
5d7836c4
JS
1299}
1300
5d7836c4
JS
1301// event handlers
1302
1303void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
1304{
1305 // true is to force the frame to close
1306 Close(true);
1307}
1308
1309void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
1310{
1311 wxString msg;
9a83f860
VZ
1312 msg.Printf( wxT("This is a demo for wxRichTextCtrl, a control for editing styled text.\n(c) Julian Smart, 2005"));
1313 wxMessageBox(msg, wxT("About wxRichTextCtrl Sample"), wxOK | wxICON_INFORMATION, this);
5d7836c4
JS
1314}
1315
1316// Forward command events to the current rich text control, if any
1317bool MyFrame::ProcessEvent(wxEvent& event)
1318{
1319 if (event.IsCommandEvent() && !event.IsKindOf(CLASSINFO(wxChildFocusEvent)))
1320 {
1321 // Problem: we can get infinite recursion because the events
1322 // climb back up to this frame, and repeat.
1323 // Assume that command events don't cause another command event
1324 // to be called, so we can rely on inCommand not being overwritten
1325
1326 static int s_eventType = 0;
1327 static wxWindowID s_id = 0;
1328
1329 if (s_id != event.GetId() && s_eventType != event.GetEventType())
1330 {
1331 s_eventType = event.GetEventType();
1332 s_id = event.GetId();
9a173d48 1333
5d7836c4 1334 wxWindow* focusWin = wxFindFocusDescendant(this);
004867db 1335 if (focusWin && focusWin->GetEventHandler()->ProcessEvent(event))
5d7836c4
JS
1336 {
1337 //s_command = NULL;
1338 s_eventType = 0;
1339 s_id = 0;
9a173d48 1340 return true;
5d7836c4
JS
1341 }
1342
1343 s_eventType = 0;
1344 s_id = 0;
1345 }
1346 else
1347 {
9a173d48 1348 return false;
5d7836c4
JS
1349 }
1350 }
1351
1352 return wxFrame::ProcessEvent(event);
1353}
1354
011b3dcb 1355void MyFrame::OnOpen(wxCommandEvent& WXUNUSED(event))
5d7836c4 1356{
9a173d48
WS
1357 wxString path;
1358 wxString filename;
1e967276
JS
1359 wxArrayInt fileTypes;
1360
1361 wxString filter = wxRichTextBuffer::GetExtWildcard(false, false, & fileTypes);
9a173d48 1362 if (!filter.empty())
5d7836c4
JS
1363 filter += wxT("|");
1364 filter += wxT("All files (*.*)|*.*");
1365
5d7836c4
JS
1366 wxFileDialog dialog(this,
1367 _("Choose a filename"),
1368 path,
1369 filename,
1370 filter,
ff3e84ff 1371 wxFD_OPEN);
5d7836c4
JS
1372
1373 if (dialog.ShowModal() == wxID_OK)
1374 {
1375 wxString path = dialog.GetPath();
9a173d48
WS
1376
1377 if (!path.empty())
5d7836c4 1378 {
1e967276 1379 int filterIndex = dialog.GetFilterIndex();
dbf38e88
WS
1380 int fileType = (filterIndex < (int) fileTypes.GetCount())
1381 ? fileTypes[filterIndex]
1382 : wxRICHTEXT_TYPE_TEXT;
1e967276 1383 m_richTextCtrl->LoadFile(path, fileType);
5d7836c4
JS
1384 }
1385 }
1386}
1387
1388void MyFrame::OnSave(wxCommandEvent& event)
1389{
9a173d48 1390 if (m_richTextCtrl->GetFilename().empty())
5d7836c4
JS
1391 {
1392 OnSaveAs(event);
1393 return;
1394 }
1395 m_richTextCtrl->SaveFile();
1396}
1397
011b3dcb 1398void MyFrame::OnSaveAs(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1399{
1400 wxString filter = wxRichTextBuffer::GetExtWildcard(false, true);
9a173d48
WS
1401 wxString path;
1402 wxString filename;
5d7836c4
JS
1403
1404 wxFileDialog dialog(this,
1405 _("Choose a filename"),
1406 path,
1407 filename,
1408 filter,
ff3e84ff 1409 wxFD_SAVE);
5d7836c4
JS
1410
1411 if (dialog.ShowModal() == wxID_OK)
1412 {
1413 wxString path = dialog.GetPath();
9a173d48
WS
1414
1415 if (!path.empty())
5d7836c4 1416 {
bec80f4f
JS
1417 wxBusyCursor busy;
1418 wxStopWatch stopwatch;
1419
5d7836c4 1420 m_richTextCtrl->SaveFile(path);
bec80f4f
JS
1421
1422 long t = stopwatch.Time();
1423 wxLogDebug(wxT("Saving took %ldms"), t);
1424 wxMessageBox(wxString::Format(wxT("Saving took %ldms"), t));
5d7836c4
JS
1425 }
1426 }
1427}
1428
011b3dcb 1429void MyFrame::OnBold(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1430{
1431 m_richTextCtrl->ApplyBoldToSelection();
1432}
1433
011b3dcb 1434void MyFrame::OnItalic(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1435{
1436 m_richTextCtrl->ApplyItalicToSelection();
1437}
1438
011b3dcb 1439void MyFrame::OnUnderline(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1440{
1441 m_richTextCtrl->ApplyUnderlineToSelection();
1442}
1443
75936ec6
JS
1444void MyFrame::OnStrikethrough(wxCommandEvent& WXUNUSED(event))
1445{
1446 m_richTextCtrl->ApplyTextEffectToSelection(wxTEXT_ATTR_EFFECT_STRIKETHROUGH);
1447}
1448
1449void MyFrame::OnSuperscript(wxCommandEvent& WXUNUSED(event))
1450{
1451 m_richTextCtrl->ApplyTextEffectToSelection(wxTEXT_ATTR_EFFECT_SUPERSCRIPT);
1452}
1453
1454void MyFrame::OnSubscript(wxCommandEvent& WXUNUSED(event))
1455{
1456 m_richTextCtrl->ApplyTextEffectToSelection(wxTEXT_ATTR_EFFECT_SUBSCRIPT);
1457}
1458
5d7836c4
JS
1459
1460void MyFrame::OnUpdateBold(wxUpdateUIEvent& event)
1461{
1462 event.Check(m_richTextCtrl->IsSelectionBold());
1463}
1464
1465void MyFrame::OnUpdateItalic(wxUpdateUIEvent& event)
1466{
1467 event.Check(m_richTextCtrl->IsSelectionItalics());
1468}
1469
1470void MyFrame::OnUpdateUnderline(wxUpdateUIEvent& event)
1471{
1472 event.Check(m_richTextCtrl->IsSelectionUnderlined());
1473}
1474
75936ec6
JS
1475void MyFrame::OnUpdateStrikethrough(wxUpdateUIEvent& event)
1476{
1477 event.Check(m_richTextCtrl->DoesSelectionHaveTextEffectFlag(wxTEXT_ATTR_EFFECT_STRIKETHROUGH));
1478}
1479
1480void MyFrame::OnUpdateSuperscript(wxUpdateUIEvent& event)
1481{
1482 event.Check(m_richTextCtrl->DoesSelectionHaveTextEffectFlag(wxTEXT_ATTR_EFFECT_SUPERSCRIPT));
1483}
1484
1485void MyFrame::OnUpdateSubscript(wxUpdateUIEvent& event)
1486{
1487 event.Check(m_richTextCtrl->DoesSelectionHaveTextEffectFlag(wxTEXT_ATTR_EFFECT_SUBSCRIPT));
1488}
1489
011b3dcb 1490void MyFrame::OnAlignLeft(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1491{
1492 m_richTextCtrl->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_LEFT);
1493}
1494
011b3dcb 1495void MyFrame::OnAlignCentre(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1496{
1497 m_richTextCtrl->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_CENTRE);
1498}
1499
011b3dcb 1500void MyFrame::OnAlignRight(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1501{
1502 m_richTextCtrl->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_RIGHT);
1503}
1504
1505void MyFrame::OnUpdateAlignLeft(wxUpdateUIEvent& event)
1506{
1507 event.Check(m_richTextCtrl->IsSelectionAligned(wxTEXT_ALIGNMENT_LEFT));
1508}
1509
1510void MyFrame::OnUpdateAlignCentre(wxUpdateUIEvent& event)
1511{
1512 event.Check(m_richTextCtrl->IsSelectionAligned(wxTEXT_ALIGNMENT_CENTRE));
1513}
1514
1515void MyFrame::OnUpdateAlignRight(wxUpdateUIEvent& event)
1516{
1517 event.Check(m_richTextCtrl->IsSelectionAligned(wxTEXT_ALIGNMENT_RIGHT));
1518}
1519
011b3dcb 1520void MyFrame::OnFont(wxCommandEvent& WXUNUSED(event))
5d7836c4 1521{
8c9c49a1
JS
1522 wxRichTextRange range;
1523 if (m_richTextCtrl->HasSelection())
1524 range = m_richTextCtrl->GetSelectionRange();
1525 else
1526 range = wxRichTextRange(0, m_richTextCtrl->GetLastPosition()+1);
1527
1528 int pages = wxRICHTEXT_FORMAT_FONT;
1529
1530 wxRichTextFormattingDialog formatDlg(pages, this);
32423dd8 1531 formatDlg.SetOptions(wxRichTextFormattingDialog::Option_AllowPixelFontSize);
8c9c49a1
JS
1532 formatDlg.GetStyle(m_richTextCtrl, range);
1533
1534 if (formatDlg.ShowModal() == wxID_OK)
1535 {
42688aea 1536 formatDlg.ApplyStyle(m_richTextCtrl, range, wxRICHTEXT_SETSTYLE_WITH_UNDO|wxRICHTEXT_SETSTYLE_OPTIMIZE|wxRICHTEXT_SETSTYLE_CHARACTERS_ONLY);
8c9c49a1 1537 }
8c9c49a1
JS
1538}
1539
cdaed652
VZ
1540void MyFrame::OnImage(wxCommandEvent& WXUNUSED(event))
1541{
1542 wxRichTextRange range;
1543 wxASSERT(m_richTextCtrl->HasSelection());
1544
1545 range = m_richTextCtrl->GetSelectionRange();
1546 wxASSERT(range.ToInternal().GetLength() == 1);
1547
603f702b 1548 wxRichTextImage* image = wxDynamicCast(m_richTextCtrl->GetFocusObject()->GetLeafObjectAtPosition(range.GetStart()), wxRichTextImage);
cdaed652
VZ
1549 if (image)
1550 {
603f702b 1551 wxRichTextObjectPropertiesDialog imageDlg(image, this);
cdaed652
VZ
1552
1553 if (imageDlg.ShowModal() == wxID_OK)
1554 {
603f702b 1555 imageDlg.ApplyStyle(m_richTextCtrl);
cdaed652
VZ
1556 }
1557 }
1558}
1559
8c9c49a1
JS
1560void MyFrame::OnParagraph(wxCommandEvent& WXUNUSED(event))
1561{
1562 wxRichTextRange range;
1563 if (m_richTextCtrl->HasSelection())
1564 range = m_richTextCtrl->GetSelectionRange();
1565 else
1566 range = wxRichTextRange(0, m_richTextCtrl->GetLastPosition()+1);
1567
1568 int pages = wxRICHTEXT_FORMAT_INDENTS_SPACING|wxRICHTEXT_FORMAT_TABS|wxRICHTEXT_FORMAT_BULLETS;
1569
1570 wxRichTextFormattingDialog formatDlg(pages, this);
1571 formatDlg.GetStyle(m_richTextCtrl, range);
1572
1573 if (formatDlg.ShowModal() == wxID_OK)
1574 {
1575 formatDlg.ApplyStyle(m_richTextCtrl, range);
1576 }
1577}
1578
1579void MyFrame::OnFormat(wxCommandEvent& WXUNUSED(event))
1580{
1581 wxRichTextRange range;
1582 if (m_richTextCtrl->HasSelection())
1583 range = m_richTextCtrl->GetSelectionRange();
1584 else
1585 range = wxRichTextRange(0, m_richTextCtrl->GetLastPosition()+1);
1586
1587 int pages = wxRICHTEXT_FORMAT_FONT|wxRICHTEXT_FORMAT_INDENTS_SPACING|wxRICHTEXT_FORMAT_TABS|wxRICHTEXT_FORMAT_BULLETS;
1588
1589 wxRichTextFormattingDialog formatDlg(pages, this);
1590 formatDlg.GetStyle(m_richTextCtrl, range);
1591
1592 if (formatDlg.ShowModal() == wxID_OK)
1593 {
1594 formatDlg.ApplyStyle(m_richTextCtrl, range);
1595 }
1596}
1597
1598void MyFrame::OnUpdateFormat(wxUpdateUIEvent& event)
1599{
1600 event.Enable(m_richTextCtrl->HasSelection());
5d7836c4
JS
1601}
1602
cdaed652
VZ
1603void MyFrame::OnUpdateImage(wxUpdateUIEvent& event)
1604{
1605 wxRichTextRange range;
1606 wxRichTextObject *obj;
1607
1608 range = m_richTextCtrl->GetSelectionRange();
1609 if (range.ToInternal().GetLength() == 1)
1610 {
603f702b 1611 obj = m_richTextCtrl->GetFocusObject()->GetLeafObjectAtPosition(range.GetStart());
cdaed652
VZ
1612 if (obj && obj->IsKindOf(CLASSINFO(wxRichTextImage)))
1613 {
1614 event.Enable(true);
1615 return;
1616 }
1617 }
1618
1619 event.Enable(false);
1620}
1621
011b3dcb 1622void MyFrame::OnIndentMore(wxCommandEvent& WXUNUSED(event))
5d7836c4 1623{
44cc96a8 1624 wxRichTextAttr attr;
5d7836c4
JS
1625 attr.SetFlags(wxTEXT_ATTR_LEFT_INDENT);
1626
1627 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1628 {
1629 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1630 if (m_richTextCtrl->HasSelection())
1631 range = m_richTextCtrl->GetSelectionRange();
1632
5d7836c4
JS
1633 attr.SetLeftIndent(attr.GetLeftIndent() + 100);
1634
1635 attr.SetFlags(wxTEXT_ATTR_LEFT_INDENT);
1636 m_richTextCtrl->SetStyle(range, attr);
1637 }
1638}
1639
011b3dcb 1640void MyFrame::OnIndentLess(wxCommandEvent& WXUNUSED(event))
5d7836c4 1641{
44cc96a8 1642 wxRichTextAttr attr;
5d7836c4
JS
1643 attr.SetFlags(wxTEXT_ATTR_LEFT_INDENT);
1644
1645 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1646 {
1647 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1648 if (m_richTextCtrl->HasSelection())
1649 range = m_richTextCtrl->GetSelectionRange();
1650
c3e54dee 1651 if (attr.GetLeftIndent() > 0)
5d7836c4 1652 {
c3e54dee 1653 attr.SetLeftIndent(wxMax(0, attr.GetLeftIndent() - 100));
9a173d48 1654
5d7836c4
JS
1655 m_richTextCtrl->SetStyle(range, attr);
1656 }
1657 }
1658}
1659
011b3dcb 1660void MyFrame::OnLineSpacingHalf(wxCommandEvent& WXUNUSED(event))
5d7836c4 1661{
44cc96a8 1662 wxRichTextAttr attr;
5d7836c4
JS
1663 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1664
1665 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1666 {
1667 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1668 if (m_richTextCtrl->HasSelection())
1669 range = m_richTextCtrl->GetSelectionRange();
1670
5d7836c4
JS
1671 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1672 attr.SetLineSpacing(15);
9a173d48 1673
5d7836c4
JS
1674 m_richTextCtrl->SetStyle(range, attr);
1675 }
1676}
1677
011b3dcb 1678void MyFrame::OnLineSpacingDouble(wxCommandEvent& WXUNUSED(event))
5d7836c4 1679{
44cc96a8 1680 wxRichTextAttr attr;
5d7836c4
JS
1681 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1682
1683 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1684 {
1685 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1686 if (m_richTextCtrl->HasSelection())
1687 range = m_richTextCtrl->GetSelectionRange();
1688
5d7836c4
JS
1689 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1690 attr.SetLineSpacing(20);
9a173d48 1691
5d7836c4
JS
1692 m_richTextCtrl->SetStyle(range, attr);
1693 }
1694}
1695
011b3dcb 1696void MyFrame::OnLineSpacingSingle(wxCommandEvent& WXUNUSED(event))
5d7836c4 1697{
44cc96a8 1698 wxRichTextAttr attr;
5d7836c4
JS
1699 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1700
1701 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1702 {
1703 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1704 if (m_richTextCtrl->HasSelection())
1705 range = m_richTextCtrl->GetSelectionRange();
1706
5d7836c4
JS
1707 attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
1708 attr.SetLineSpacing(0); // Can also use 10
9a173d48 1709
5d7836c4
JS
1710 m_richTextCtrl->SetStyle(range, attr);
1711 }
1712}
1713
011b3dcb 1714void MyFrame::OnParagraphSpacingMore(wxCommandEvent& WXUNUSED(event))
5d7836c4 1715{
44cc96a8 1716 wxRichTextAttr attr;
5d7836c4
JS
1717 attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER);
1718
1719 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1720 {
1721 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1722 if (m_richTextCtrl->HasSelection())
1723 range = m_richTextCtrl->GetSelectionRange();
1724
5d7836c4
JS
1725 attr.SetParagraphSpacingAfter(attr.GetParagraphSpacingAfter() + 20);
1726
1727 attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER);
1728 m_richTextCtrl->SetStyle(range, attr);
1729 }
1730}
1731
011b3dcb 1732void MyFrame::OnParagraphSpacingLess(wxCommandEvent& WXUNUSED(event))
5d7836c4 1733{
44cc96a8 1734 wxRichTextAttr attr;
5d7836c4
JS
1735 attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER);
1736
1737 if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr))
1738 {
1739 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
1740 if (m_richTextCtrl->HasSelection())
1741 range = m_richTextCtrl->GetSelectionRange();
1742
1743 if (attr.GetParagraphSpacingAfter() >= 20)
1744 {
5d7836c4 1745 attr.SetParagraphSpacingAfter(attr.GetParagraphSpacingAfter() - 20);
9a173d48 1746
5d7836c4
JS
1747 attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER);
1748 m_richTextCtrl->SetStyle(range, attr);
1749 }
1750 }
1751}
1752
99404ab0
JS
1753void MyFrame::OnReload(wxCommandEvent& WXUNUSED(event))
1754{
1755 m_richTextCtrl->Clear();
1756 WriteInitialText();
1757}
1758
011b3dcb 1759void MyFrame::OnViewHTML(wxCommandEvent& WXUNUSED(event))
5d7836c4
JS
1760{
1761 wxDialog dialog(this, wxID_ANY, _("HTML"), wxDefaultPosition, wxSize(500, 400), wxDEFAULT_DIALOG_STYLE);
1762
1763 wxBoxSizer* boxSizer = new wxBoxSizer(wxVERTICAL);
1764 dialog.SetSizer(boxSizer);
1765
1766 wxHtmlWindow* win = new wxHtmlWindow(& dialog, wxID_ANY, wxDefaultPosition, wxSize(500, 400), wxSUNKEN_BORDER);
1767 boxSizer->Add(win, 1, wxALL, 5);
1768
1769 wxButton* cancelButton = new wxButton(& dialog, wxID_CANCEL, wxT("&Close"));
1770 boxSizer->Add(cancelButton, 0, wxALL|wxCENTRE, 5);
1771
1772 wxString text;
1773 wxStringOutputStream strStream(& text);
1774
1775 wxRichTextHTMLHandler htmlHandler;
720cc10a 1776 htmlHandler.SetFlags(wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_MEMORY);
c3e54dee 1777
50f65288
WS
1778 wxArrayInt fontSizeMapping;
1779 fontSizeMapping.Add(7);
1780 fontSizeMapping.Add(9);
1781 fontSizeMapping.Add(11);
1782 fontSizeMapping.Add(12);
1783 fontSizeMapping.Add(14);
1784 fontSizeMapping.Add(22);
1785 fontSizeMapping.Add(100);
c3e54dee 1786
50f65288 1787 htmlHandler.SetFontSizeMapping(fontSizeMapping);
720cc10a 1788
5d7836c4
JS
1789 if (htmlHandler.SaveFile(& m_richTextCtrl->GetBuffer(), strStream))
1790 {
1791 win->SetPage(text);
1792 }
1793
1794 boxSizer->Fit(& dialog);
1795
1796 dialog.ShowModal();
720cc10a
JS
1797
1798 // Now delete the temporary in-memory images
1799 htmlHandler.DeleteTemporaryImages();
5d7836c4 1800}
fe5aa22c
JS
1801
1802// Demonstrates how you can change the style sheets and have the changes
1803// reflected in the control content without wiping out character formatting.
1804
1805void MyFrame::OnSwitchStyleSheets(wxCommandEvent& WXUNUSED(event))
1806{
1807 static wxRichTextStyleSheet* gs_AlternateStyleSheet = NULL;
1808
e4723634 1809 wxRichTextStyleListCtrl *styleList = (wxRichTextStyleListCtrl*) FindWindow(ID_RICHTEXT_STYLE_LIST);
fe5aa22c
JS
1810 wxRichTextStyleComboCtrl* styleCombo = (wxRichTextStyleComboCtrl*) FindWindow(ID_RICHTEXT_STYLE_COMBO);
1811
8881d9f0 1812 wxRichTextStyleSheet* sheet = m_richTextCtrl->GetStyleSheet();
fe5aa22c
JS
1813
1814 // One-time creation of an alternate style sheet
1815 if (!gs_AlternateStyleSheet)
1816 {
1817 gs_AlternateStyleSheet = new wxRichTextStyleSheet(*sheet);
1818
1819 // Make some modifications
1820 for (int i = 0; i < (int) gs_AlternateStyleSheet->GetParagraphStyleCount(); i++)
1821 {
1822 wxRichTextParagraphStyleDefinition* def = gs_AlternateStyleSheet->GetParagraphStyle(i);
1823
1824 if (def->GetStyle().HasTextColour())
1825 def->GetStyle().SetTextColour(*wxBLUE);
1826
1827 if (def->GetStyle().HasAlignment())
1828 {
1829 if (def->GetStyle().GetAlignment() == wxTEXT_ALIGNMENT_CENTRE)
1830 def->GetStyle().SetAlignment(wxTEXT_ALIGNMENT_RIGHT);
1831 else if (def->GetStyle().GetAlignment() == wxTEXT_ALIGNMENT_LEFT)
1832 def->GetStyle().SetAlignment(wxTEXT_ALIGNMENT_CENTRE);
1833 }
1834 if (def->GetStyle().HasLeftIndent())
1835 {
1836 def->GetStyle().SetLeftIndent(def->GetStyle().GetLeftIndent() * 2);
1837 }
1838 }
1839 }
1840
1841 // Switch sheets
1842 wxRichTextStyleSheet* tmp = gs_AlternateStyleSheet;
1843 gs_AlternateStyleSheet = sheet;
1844 sheet = tmp;
1845
8881d9f0
JS
1846 m_richTextCtrl->SetStyleSheet(sheet);
1847 m_richTextCtrl->ApplyStyleSheet(sheet); // Makes the control reflect the new style definitions
fe5aa22c
JS
1848
1849 styleList->SetStyleSheet(sheet);
1850 styleList->UpdateStyles();
1851
1852 styleCombo->SetStyleSheet(sheet);
1853 styleCombo->UpdateStyles();
1854}
8c9c49a1 1855
e4723634
JS
1856void MyFrame::OnManageStyles(wxCommandEvent& WXUNUSED(event))
1857{
8881d9f0 1858 wxRichTextStyleSheet* sheet = m_richTextCtrl->GetStyleSheet();
e4723634
JS
1859
1860 int flags = wxRICHTEXT_ORGANISER_CREATE_STYLES|wxRICHTEXT_ORGANISER_EDIT_STYLES;
1861
1862 wxRichTextStyleOrganiserDialog dlg(flags, sheet, NULL, this, wxID_ANY, _("Style Manager"));
1863 dlg.ShowModal();
1864}
1865
8c9c49a1
JS
1866void MyFrame::OnInsertSymbol(wxCommandEvent& WXUNUSED(event))
1867{
44cc96a8 1868 wxRichTextAttr attr;
8c9c49a1 1869 attr.SetFlags(wxTEXT_ATTR_FONT);
8881d9f0 1870 m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr);
8c9c49a1
JS
1871
1872 wxString currentFontName;
a1b806b9 1873 if (attr.HasFont() && attr.GetFont().IsOk())
8c9c49a1
JS
1874 currentFontName = attr.GetFont().GetFaceName();
1875
1876 // Don't set the initial font in the dialog (so the user is choosing
1877 // 'normal text', i.e. the current font) but do tell the dialog
1878 // what 'normal text' is.
1879
1880 wxSymbolPickerDialog dlg(wxT("*"), wxEmptyString, currentFontName, this);
1881
1882 if (dlg.ShowModal() == wxID_OK)
1883 {
1884 if (dlg.HasSelection())
1885 {
8881d9f0 1886 long insertionPoint = m_richTextCtrl->GetInsertionPoint();
8c9c49a1 1887
8881d9f0 1888 m_richTextCtrl->WriteText(dlg.GetSymbol());
8c9c49a1
JS
1889
1890 if (!dlg.UseNormalFont())
1891 {
1892 wxFont font(attr.GetFont());
23c386ba 1893 font.SetFaceName(dlg.GetFontName());
8c9c49a1 1894 attr.SetFont(font);
8881d9f0 1895 m_richTextCtrl->SetStyle(insertionPoint, insertionPoint+1, attr);
8c9c49a1
JS
1896 }
1897 }
1898 }
1899}
082cfe55
JS
1900
1901void MyFrame::OnNumberList(wxCommandEvent& WXUNUSED(event))
1902{
8881d9f0 1903 if (m_richTextCtrl->HasSelection())
082cfe55 1904 {
8881d9f0
JS
1905 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1906 m_richTextCtrl->SetListStyle(range, wxT("Numbered List 1"), wxRICHTEXT_SETSTYLE_WITH_UNDO|wxRICHTEXT_SETSTYLE_RENUMBER);
082cfe55
JS
1907 }
1908}
1909
e4723634
JS
1910void MyFrame::OnBulletsAndNumbering(wxCommandEvent& WXUNUSED(event))
1911{
8881d9f0 1912 wxRichTextStyleSheet* sheet = m_richTextCtrl->GetStyleSheet();
e4723634
JS
1913
1914 int flags = wxRICHTEXT_ORGANISER_BROWSE_NUMBERING;
1915
8881d9f0 1916 wxRichTextStyleOrganiserDialog dlg(flags, sheet, m_richTextCtrl, this, wxID_ANY, _("Bullets and Numbering"));
e4723634
JS
1917 if (dlg.ShowModal() == wxID_OK)
1918 {
1919 if (dlg.GetSelectedStyleDefinition())
1920 dlg.ApplyStyle();
1921 }
1922}
1923
082cfe55
JS
1924void MyFrame::OnItemizeList(wxCommandEvent& WXUNUSED(event))
1925{
8881d9f0 1926 if (m_richTextCtrl->HasSelection())
082cfe55 1927 {
8881d9f0
JS
1928 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1929 m_richTextCtrl->SetListStyle(range, wxT("Bullet List 1"));
082cfe55
JS
1930 }
1931}
1932
1933void MyFrame::OnRenumberList(wxCommandEvent& WXUNUSED(event))
1934{
8881d9f0 1935 if (m_richTextCtrl->HasSelection())
082cfe55 1936 {
8881d9f0
JS
1937 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1938 m_richTextCtrl->NumberList(range, NULL, wxRICHTEXT_SETSTYLE_WITH_UNDO|wxRICHTEXT_SETSTYLE_RENUMBER);
082cfe55
JS
1939 }
1940}
1941
1942void MyFrame::OnPromoteList(wxCommandEvent& WXUNUSED(event))
1943{
8881d9f0 1944 if (m_richTextCtrl->HasSelection())
082cfe55 1945 {
8881d9f0
JS
1946 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1947 m_richTextCtrl->PromoteList(1, range, NULL);
082cfe55
JS
1948 }
1949}
1950
1951void MyFrame::OnDemoteList(wxCommandEvent& WXUNUSED(event))
1952{
8881d9f0 1953 if (m_richTextCtrl->HasSelection())
082cfe55 1954 {
8881d9f0
JS
1955 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1956 m_richTextCtrl->PromoteList(-1, range, NULL);
082cfe55
JS
1957 }
1958}
1959
1960void MyFrame::OnClearList(wxCommandEvent& WXUNUSED(event))
1961{
8881d9f0 1962 if (m_richTextCtrl->HasSelection())
082cfe55 1963 {
8881d9f0
JS
1964 wxRichTextRange range = m_richTextCtrl->GetSelectionRange();
1965 m_richTextCtrl->ClearListStyle(range);
082cfe55
JS
1966 }
1967}
1968
f4ac09e8
JS
1969void MyFrame::OnTableAddColumn(wxCommandEvent& WXUNUSED(event))
1970{
1971 wxRichTextTable* table = wxDynamicCast(m_richTextCtrl->FindTable(), wxRichTextTable);
1972 if (table)
1973 {
1974 wxRichTextAttr cellAttr = table->GetCell(0, 0)->GetAttributes();
1975 table->AddColumns(table->GetColumnCount(), 1, cellAttr);
1976 }
1977}
1978
1979void MyFrame::OnTableAddRow(wxCommandEvent& WXUNUSED(event))
1980{
1981 wxRichTextTable* table = wxDynamicCast(m_richTextCtrl->FindTable(), wxRichTextTable);
1982 if (table)
1983 {
1984 wxRichTextAttr cellAttr = table->GetCell(0, 0)->GetAttributes();
1985 table->AddRows(table->GetRowCount(), 1, cellAttr);
1986 }
1987}
1988
1989void MyFrame::OnTableDeleteColumn(wxCommandEvent& WXUNUSED(event))
1990{
1991 wxRichTextTable* table = wxDynamicCast(m_richTextCtrl->FindTable(), wxRichTextTable);
1992 if (table)
1993 {
1994 int col = table->GetFocusedCell().GetCol();
1995 if (col == -1)
1996 {
1997 col = table->GetColumnCount() - 1;
1998 }
1999
2000 table->DeleteColumns(col, 1);
2001 }
2002}
2003
2004void MyFrame::OnTableDeleteRow(wxCommandEvent& WXUNUSED(event))
2005{
2006 wxRichTextTable* table = wxDynamicCast(m_richTextCtrl->FindTable(), wxRichTextTable);
2007 if (table)
2008 {
2009 int row = table->GetFocusedCell().GetRow();
2010 if (row == -1)
2011 {
2012 row = table->GetRowCount() - 1;
2013 }
2014
2015 table->DeleteRows(row, 1);
2016 }
2017}
2018
2019void MyFrame::OnTableFocusedUpdateUI(wxUpdateUIEvent& event)
2020{
2021 event.Enable(m_richTextCtrl->FindTable() != NULL);
2022}
2023
2024void MyFrame::OnTableHasCellsUpdateUI(wxUpdateUIEvent& event)
2025{
2026 bool enable(false);
2027 wxRichTextTable* table = wxDynamicCast(m_richTextCtrl->FindTable(), wxRichTextTable);
2028 if (table)
2029 {
2030 if (event.GetId() == ID_TABLE_DELETE_COLUMN)
2031 {
2032 enable = table->GetColumnCount() > 1;
2033 }
2034 else
2035 {
2036 enable = table->GetRowCount() > 1;
2037 }
2038 }
2039
2040 event.Enable(enable);
2041}
2042
720cc10a
JS
2043void MyFrame::OnInsertURL(wxCommandEvent& WXUNUSED(event))
2044{
2045 wxString url = wxGetTextFromUser(_("URL:"), _("Insert URL"));
2046 if (!url.IsEmpty())
2047 {
720cc10a
JS
2048 // Make a style suitable for showing a URL
2049 wxRichTextAttr urlStyle;
2050 urlStyle.SetTextColour(*wxBLUE);
2051 urlStyle.SetFontUnderlined(true);
c3e54dee 2052
8881d9f0
JS
2053 m_richTextCtrl->BeginStyle(urlStyle);
2054 m_richTextCtrl->BeginURL(url);
2055 m_richTextCtrl->WriteText(url);
2056 m_richTextCtrl->EndURL();
2057 m_richTextCtrl->EndStyle();
720cc10a
JS
2058 }
2059}
2060
cdaed652
VZ
2061void MyFrame::OnInsertImage(wxCommandEvent& WXUNUSED(event))
2062{
2063 wxFileDialog dialog(this, _("Choose an image"), "", "", "BMP and GIF files (*.bmp;*.gif)|*.bmp;*.gif|PNG files (*.png)|*.png");
2064 if (dialog.ShowModal() == wxID_OK)
2065 {
2066 wxString path = dialog.GetPath();
2067 m_richTextCtrl->WriteImage(path, wxBITMAP_TYPE_ANY);
2068 }
2069}
2070
720cc10a
JS
2071void MyFrame::OnURL(wxTextUrlEvent& event)
2072{
2073 wxMessageBox(event.GetString());
2074}
2075
2076// Veto style sheet replace events when loading from XML, since we want
2077// to keep the original style sheet.
2078void MyFrame::OnStyleSheetReplacing(wxRichTextEvent& event)
2079{
2080 event.Veto();
2081}
8881d9f0
JS
2082
2083void MyFrame::OnPrint(wxCommandEvent& WXUNUSED(event))
2084{
2085 wxGetApp().GetPrinting()->PrintBuffer(m_richTextCtrl->GetBuffer());
2086}
2087
2088void MyFrame::OnPreview(wxCommandEvent& WXUNUSED(event))
2089{
2090 wxGetApp().GetPrinting()->PreviewBuffer(m_richTextCtrl->GetBuffer());
2091}
2092
2093void MyFrame::OnPageSetup(wxCommandEvent& WXUNUSED(event))
2094{
24777478
JS
2095 wxDialog dialog(this, wxID_ANY, wxT("Testing"), wxPoint(10, 10), wxSize(400, 300), wxDEFAULT_DIALOG_STYLE);
2096
2097 wxNotebook* nb = new wxNotebook(& dialog, wxID_ANY, wxPoint(5, 5), wxSize(300, 250));
2098 wxPanel* panel = new wxPanel(nb, wxID_ANY, wxDefaultPosition, wxDefaultSize);
2099 wxPanel* panel2 = new wxPanel(nb, wxID_ANY, wxDefaultPosition, wxDefaultSize);
2100
d275b15d 2101 new wxRichTextCtrl(panel, wxID_ANY, wxEmptyString, wxPoint(5, 5), wxSize(200, 150), wxVSCROLL|wxTE_READONLY);
24777478
JS
2102 nb->AddPage(panel, wxT("Page 1"));
2103
d275b15d 2104 new wxRichTextCtrl(panel2, wxID_ANY, wxEmptyString, wxPoint(5, 5), wxSize(200, 150), wxVSCROLL|wxTE_READONLY);
24777478
JS
2105 nb->AddPage(panel2, wxT("Page 2"));
2106
d275b15d 2107 new wxButton(& dialog, wxID_OK, wxT("OK"), wxPoint(5, 180));
24777478
JS
2108
2109 dialog.ShowModal();
2110
2111// wxGetApp().GetPrinting()->PageSetup();
8881d9f0 2112}
cc2aecde 2113
32423dd8
JS
2114void MyFrame::OnSetFontScale(wxCommandEvent& WXUNUSED(event))
2115{
2116 wxString value = wxString::Format(wxT("%g"), m_richTextCtrl->GetFontScale());
2117 wxString text = wxGetTextFromUser(wxT("Enter a text scale factor:"), wxT("Text Scale Factor"), value, wxGetTopLevelParent(this));
2118 if (!text.IsEmpty() && value != text)
2119 {
2120 double scale = 1.0;
2121 wxSscanf(text, wxT("%lf"), & scale);
2122 m_richTextCtrl->SetFontScale(scale, true);
2123 }
2124}
2125
2126void MyFrame::OnSetDimensionScale(wxCommandEvent& WXUNUSED(event))
2127{
2128 wxString value = wxString::Format(wxT("%g"), m_richTextCtrl->GetDimensionScale());
2129 wxString text = wxGetTextFromUser(wxT("Enter a dimension scale factor:"), wxT("Dimension Scale Factor"), value, wxGetTopLevelParent(this));
2130 if (!text.IsEmpty() && value != text)
2131 {
2132 double scale = 1.0;
2133 wxSscanf(text, wxT("%lf"), & scale);
2134 m_richTextCtrl->SetDimensionScale(scale, true);
2135 }
2136}
2137
cc2aecde
JS
2138void MyRichTextCtrl::PrepareContent(wxRichTextParagraphLayoutBox& container)
2139{
2140 if (IsLocked())
2141 {
2142 // Lock all content that's about to be added to the control
2143 wxRichTextObjectList::compatibility_iterator node = container.GetChildren().GetFirst();
2144 while (node)
2145 {
2146 wxRichTextParagraph* para = wxDynamicCast(node->GetData(), wxRichTextParagraph);
2147 if (para)
2148 {
2149 wxRichTextObjectList::compatibility_iterator childNode = para->GetChildren().GetFirst();
2150 while (childNode)
2151 {
2152 wxRichTextObject* obj = childNode->GetData();
2153 obj->GetProperties().SetProperty(wxT("Lock"), m_lockId);
2154
2155 childNode = childNode->GetNext();
2156 }
2157 }
2158 node = node->GetNext();
2159 }
2160 }
2161}
2162
2163bool MyRichTextCtrl::CanDeleteRange(wxRichTextParagraphLayoutBox& container, const wxRichTextRange& range) const
2164{
2165 long i;
2166 for (i = range.GetStart(); i < range.GetEnd(); i++)
2167 {
2168 wxRichTextObject* obj = container.GetLeafObjectAtPosition(i);
2169 if (obj && obj->GetProperties().HasProperty(wxT("Lock")))
2170 {
2171 return false;
2172 }
2173 }
2174 return true;
2175}
2176
2177bool MyRichTextCtrl::CanInsertContent(wxRichTextParagraphLayoutBox& container, long pos) const
2178{
2179 wxRichTextObject* child1 = container.GetLeafObjectAtPosition(pos);
2180 wxRichTextObject* child2 = container.GetLeafObjectAtPosition(pos-1);
2181
2182 long lock1 = -1, lock2 = -1;
2183
2184 if (child1 && child1->GetProperties().HasProperty(wxT("Lock")))
2185 lock1 = child1->GetProperties().GetPropertyLong(wxT("Lock"));
2186 if (child2 && child2->GetProperties().HasProperty(wxT("Lock")))
2187 lock2 = child2->GetProperties().GetPropertyLong(wxT("Lock"));
2188
2189 if (lock1 != -1 && lock1 == lock2)
2190 return false;
2191
2192 // Don't allow insertion before a locked object if it's at the beginning of the buffer.
2193 if (pos == 0 && lock1 != -1)
2194 return false;
2195
2196 return true;
2197}
2198
2199
2200class wxRichTextEnhancedDrawingHandler: public wxRichTextDrawingHandler
2201{
2202public:
2203 wxRichTextEnhancedDrawingHandler()
2204 {
2205 SetName(wxT("enhanceddrawing"));
2206 m_lockBackgroundColour = wxColour(220, 220, 220);
2207 }
2208
2209 /**
2210 Returns @true if this object has virtual attributes that we can provide.
2211 */
2212 virtual bool HasVirtualAttributes(wxRichTextObject* obj) const;
2213
2214 /**
2215 Provides virtual attributes that we can provide.
2216 */
2217 virtual bool GetVirtualAttributes(wxRichTextAttr& attr, wxRichTextObject* obj) const;
2218
f7667b84
JS
2219 /**
2220 Gets the count for mixed virtual attributes for individual positions within the object.
2221 For example, individual characters within a text object may require special highlighting.
2222 */
2223 virtual int GetVirtualSubobjectAttributesCount(wxRichTextObject* WXUNUSED(obj)) const { return 0; }
2224
2225 /**
2226 Gets the mixed virtual attributes for individual positions within the object.
2227 For example, individual characters within a text object may require special highlighting.
2228 Returns the number of virtual attributes found.
2229 */
2230 virtual int GetVirtualSubobjectAttributes(wxRichTextObject* WXUNUSED(obj), wxArrayInt& WXUNUSED(positions), wxRichTextAttrArray& WXUNUSED(attributes)) const { return 0; }
2231
2232 /**
2233 Do we have virtual text for this object? Virtual text allows an application
2234 to replace characters in an object for editing and display purposes, for example
2235 for highlighting special characters.
2236 */
2237 virtual bool HasVirtualText(const wxRichTextPlainText* WXUNUSED(obj)) const { return false; }
2238
2239 /**
2240 Gets the virtual text for this object.
2241 */
2242 virtual bool GetVirtualText(const wxRichTextPlainText* WXUNUSED(obj), wxString& WXUNUSED(text)) const { return false; }
2243
cc2aecde
JS
2244 wxColour m_lockBackgroundColour;
2245};
2246
2247bool wxRichTextEnhancedDrawingHandler::HasVirtualAttributes(wxRichTextObject* obj) const
2248{
2249 return obj->GetProperties().HasProperty(wxT("Lock"));
2250}
2251
2252bool wxRichTextEnhancedDrawingHandler::GetVirtualAttributes(wxRichTextAttr& attr, wxRichTextObject* obj) const
2253{
2254 if (obj->GetProperties().HasProperty(wxT("Lock")))
2255 {
2256 attr.SetBackgroundColour(m_lockBackgroundColour);
2257 return true;
2258 }
2259 return false;
2260}
2261
2262void MyRichTextCtrl::SetEnhancedDrawingHandler()
2263{
2264 wxRichTextBuffer::AddDrawingHandler(new wxRichTextEnhancedDrawingHandler);
2265}
f4ac09e8
JS
2266
2267wxRichTextObject* MyRichTextCtrl::FindCurrentPosition() const
2268{
2269 long position = -1;
2270
2271 if (HasSelection()) // First see if there's a selection
2272 {
2273 wxRichTextRange range = GetSelectionRange();
2274 if (range.ToInternal().GetLength() == 1)
2275 {
2276 position = range.GetStart();
2277 }
2278 }
2279 if (position == -1) // Failing that, near cursor
2280 {
2281 position = GetAdjustedCaretPosition(GetCaretPosition());
2282 }
2283
2284
2285 wxRichTextObject* obj = GetFocusObject()->GetLeafObjectAtPosition(position);
2286
2287 return obj;
2288}
2289
2290wxRichTextTable* MyRichTextCtrl::FindTable() const
2291{
2292 wxRichTextObject* obj = FindCurrentPosition();
2293
2294 // It could be a table or a cell (or neither)
2295 wxRichTextTable* table = wxDynamicCast(obj, wxRichTextTable);
2296 if (table)
2297 {
2298 return table;
2299 }
2300
2301 while (obj)
2302 {
2303 obj = obj->GetParent();
2304 wxRichTextTable* table = wxDynamicCast(obj, wxRichTextTable);
2305 if (table)
2306 {
2307 return table;
2308 }
2309 }
2310
2311 return NULL;
2312}