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