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