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