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