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