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