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