]>
Commit | Line | Data |
---|---|---|
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" | |
37 | ||
1226b3b3 WS |
38 | #ifndef __WXMSW__ |
39 | #include "../sample.xpm" | |
40 | #endif | |
41 | ||
5d7836c4 JS |
42 | #include "bitmaps/smiley.xpm" |
43 | // #include "bitmaps/idea.xpm" | |
44 | #include "bitmaps/zebra.xpm" | |
45 | ||
46 | #include "bitmaps/open.xpm" | |
47 | #include "bitmaps/save.xpm" | |
48 | #include "bitmaps/copy.xpm" | |
49 | #include "bitmaps/cut.xpm" | |
50 | #include "bitmaps/paste.xpm" | |
51 | #include "bitmaps/undo.xpm" | |
52 | #include "bitmaps/redo.xpm" | |
53 | #include "bitmaps/bold.xpm" | |
54 | #include "bitmaps/italic.xpm" | |
55 | #include "bitmaps/underline.xpm" | |
56 | ||
57 | #include "bitmaps/alignleft.xpm" | |
58 | #include "bitmaps/alignright.xpm" | |
59 | #include "bitmaps/centre.xpm" | |
60 | #include "bitmaps/font.xpm" | |
61 | #include "bitmaps/indentless.xpm" | |
62 | #include "bitmaps/indentmore.xpm" | |
63 | ||
011b3dcb JS |
64 | #include "wx/richtext/richtextctrl.h" |
65 | #include "wx/richtext/richtextstyles.h" | |
66 | #include "wx/richtext/richtextxml.h" | |
b71e9aa4 | 67 | #include "wx/richtext/richtexthtml.h" |
8c9c49a1 JS |
68 | #include "wx/richtext/richtextformatdlg.h" |
69 | #include "wx/richtext/richtextsymboldlg.h" | |
5d7836c4 JS |
70 | |
71 | // ---------------------------------------------------------------------------- | |
72 | // resources | |
73 | // ---------------------------------------------------------------------------- | |
74 | ||
75 | // ---------------------------------------------------------------------------- | |
76 | // private classes | |
77 | // ---------------------------------------------------------------------------- | |
78 | ||
79 | // Define a new application type, each program should derive a class from wxApp | |
80 | class MyApp : public wxApp | |
81 | { | |
82 | public: | |
83 | // override base class virtuals | |
84 | // ---------------------------- | |
85 | ||
86 | // this one is called on application startup and is a good place for the app | |
87 | // initialization (doing it here and not in the ctor allows to have an error | |
88 | // return: if OnInit() returns false, the application terminates) | |
89 | virtual bool OnInit(); | |
90 | virtual int OnExit(); | |
91 | ||
92 | void CreateStyles(); | |
93 | ||
94 | wxRichTextStyleSheet* GetStyleSheet() const { return m_styleSheet; } | |
95 | ||
96 | wxRichTextStyleSheet* m_styleSheet; | |
97 | }; | |
98 | ||
99 | // Define a new frame type: this is going to be our main frame | |
100 | class MyFrame : public wxFrame | |
101 | { | |
102 | public: | |
103 | // ctor(s) | |
104 | MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos = wxDefaultPosition, | |
105 | const wxSize& size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE); | |
106 | ||
107 | // event handlers (these functions should _not_ be virtual) | |
108 | void OnQuit(wxCommandEvent& event); | |
109 | void OnAbout(wxCommandEvent& event); | |
110 | ||
111 | void OnOpen(wxCommandEvent& event); | |
112 | void OnSave(wxCommandEvent& event); | |
113 | void OnSaveAs(wxCommandEvent& event); | |
114 | ||
115 | void OnBold(wxCommandEvent& event); | |
116 | void OnItalic(wxCommandEvent& event); | |
117 | void OnUnderline(wxCommandEvent& event); | |
118 | ||
119 | void OnUpdateBold(wxUpdateUIEvent& event); | |
120 | void OnUpdateItalic(wxUpdateUIEvent& event); | |
121 | void OnUpdateUnderline(wxUpdateUIEvent& event); | |
122 | ||
123 | void OnAlignLeft(wxCommandEvent& event); | |
124 | void OnAlignCentre(wxCommandEvent& event); | |
125 | void OnAlignRight(wxCommandEvent& event); | |
126 | ||
127 | void OnUpdateAlignLeft(wxUpdateUIEvent& event); | |
128 | void OnUpdateAlignCentre(wxUpdateUIEvent& event); | |
129 | void OnUpdateAlignRight(wxUpdateUIEvent& event); | |
130 | ||
5d7836c4 JS |
131 | void OnIndentMore(wxCommandEvent& event); |
132 | void OnIndentLess(wxCommandEvent& event); | |
133 | ||
8c9c49a1 JS |
134 | void OnFont(wxCommandEvent& event); |
135 | void OnParagraph(wxCommandEvent& event); | |
136 | void OnFormat(wxCommandEvent& event); | |
137 | void OnUpdateFormat(wxUpdateUIEvent& event); | |
138 | ||
139 | void OnInsertSymbol(wxCommandEvent& event); | |
140 | ||
5d7836c4 JS |
141 | void OnLineSpacingHalf(wxCommandEvent& event); |
142 | void OnLineSpacingDouble(wxCommandEvent& event); | |
143 | void OnLineSpacingSingle(wxCommandEvent& event); | |
144 | ||
145 | void OnParagraphSpacingMore(wxCommandEvent& event); | |
146 | void OnParagraphSpacingLess(wxCommandEvent& event); | |
147 | ||
148 | void OnViewHTML(wxCommandEvent& event); | |
149 | ||
fe5aa22c JS |
150 | void OnSwitchStyleSheets(wxCommandEvent& event); |
151 | ||
5d7836c4 JS |
152 | // Forward command events to the current rich text control, if any |
153 | bool ProcessEvent(wxEvent& event); | |
154 | ||
155 | private: | |
156 | // any class wishing to process wxWidgets events must use this macro | |
157 | DECLARE_EVENT_TABLE() | |
158 | ||
159 | wxRichTextCtrl* m_richTextCtrl; | |
160 | }; | |
161 | ||
162 | // ---------------------------------------------------------------------------- | |
163 | // constants | |
164 | // ---------------------------------------------------------------------------- | |
165 | ||
166 | // IDs for the controls and the menu commands | |
167 | enum | |
168 | { | |
169 | // menu items | |
170 | ID_Quit = wxID_EXIT, | |
171 | ID_About = wxID_ABOUT, | |
172 | ||
173 | ID_FORMAT_BOLD = 100, | |
174 | ID_FORMAT_ITALIC, | |
175 | ID_FORMAT_UNDERLINE, | |
176 | ID_FORMAT_FONT, | |
8c9c49a1 JS |
177 | ID_FORMAT_PARAGRAPH, |
178 | ID_FORMAT_CONTENT, | |
179 | ||
180 | ID_INSERT_SYMBOL, | |
5d7836c4 JS |
181 | |
182 | ID_FORMAT_ALIGN_LEFT, | |
183 | ID_FORMAT_ALIGN_CENTRE, | |
184 | ID_FORMAT_ALIGN_RIGHT, | |
185 | ||
186 | ID_FORMAT_INDENT_MORE, | |
187 | ID_FORMAT_INDENT_LESS, | |
188 | ||
189 | ID_FORMAT_PARAGRAPH_SPACING_MORE, | |
190 | ID_FORMAT_PARAGRAPH_SPACING_LESS, | |
191 | ||
192 | ID_FORMAT_LINE_SPACING_HALF, | |
193 | ID_FORMAT_LINE_SPACING_DOUBLE, | |
194 | ID_FORMAT_LINE_SPACING_SINGLE, | |
195 | ||
fe5aa22c JS |
196 | ID_VIEW_HTML, |
197 | ID_SWITCH_STYLE_SHEETS, | |
198 | ||
199 | ID_RICHTEXT_CTRL, | |
200 | ID_RICHTEXT_STYLE_LIST, | |
201 | ID_RICHTEXT_STYLE_COMBO | |
5d7836c4 JS |
202 | }; |
203 | ||
204 | // ---------------------------------------------------------------------------- | |
205 | // event tables and other macros for wxWidgets | |
206 | // ---------------------------------------------------------------------------- | |
207 | ||
208 | // the event tables connect the wxWidgets events with the functions (event | |
209 | // handlers) which process them. It can be also done at run-time, but for the | |
210 | // simple menu events like this the static method is much simpler. | |
211 | BEGIN_EVENT_TABLE(MyFrame, wxFrame) | |
212 | EVT_MENU(ID_Quit, MyFrame::OnQuit) | |
213 | EVT_MENU(ID_About, MyFrame::OnAbout) | |
214 | ||
215 | EVT_MENU(wxID_OPEN, MyFrame::OnOpen) | |
216 | EVT_MENU(wxID_SAVE, MyFrame::OnSave) | |
217 | EVT_MENU(wxID_SAVEAS, MyFrame::OnSaveAs) | |
218 | ||
219 | EVT_MENU(ID_FORMAT_BOLD, MyFrame::OnBold) | |
220 | EVT_MENU(ID_FORMAT_ITALIC, MyFrame::OnItalic) | |
221 | EVT_MENU(ID_FORMAT_UNDERLINE, MyFrame::OnUnderline) | |
222 | ||
223 | EVT_UPDATE_UI(ID_FORMAT_BOLD, MyFrame::OnUpdateBold) | |
224 | EVT_UPDATE_UI(ID_FORMAT_ITALIC, MyFrame::OnUpdateItalic) | |
225 | EVT_UPDATE_UI(ID_FORMAT_UNDERLINE, MyFrame::OnUpdateUnderline) | |
226 | ||
227 | EVT_MENU(ID_FORMAT_ALIGN_LEFT, MyFrame::OnAlignLeft) | |
228 | EVT_MENU(ID_FORMAT_ALIGN_CENTRE, MyFrame::OnAlignCentre) | |
229 | EVT_MENU(ID_FORMAT_ALIGN_RIGHT, MyFrame::OnAlignRight) | |
230 | ||
231 | EVT_UPDATE_UI(ID_FORMAT_ALIGN_LEFT, MyFrame::OnUpdateAlignLeft) | |
232 | EVT_UPDATE_UI(ID_FORMAT_ALIGN_CENTRE, MyFrame::OnUpdateAlignCentre) | |
233 | EVT_UPDATE_UI(ID_FORMAT_ALIGN_RIGHT, MyFrame::OnUpdateAlignRight) | |
234 | ||
235 | EVT_MENU(ID_FORMAT_FONT, MyFrame::OnFont) | |
8c9c49a1 JS |
236 | EVT_MENU(ID_FORMAT_PARAGRAPH, MyFrame::OnParagraph) |
237 | EVT_MENU(ID_FORMAT_CONTENT, MyFrame::OnFormat) | |
238 | EVT_UPDATE_UI(ID_FORMAT_CONTENT, MyFrame::OnUpdateFormat) | |
239 | EVT_UPDATE_UI(ID_FORMAT_FONT, MyFrame::OnUpdateFormat) | |
240 | EVT_UPDATE_UI(ID_FORMAT_PARAGRAPH, MyFrame::OnUpdateFormat) | |
5d7836c4 JS |
241 | EVT_MENU(ID_FORMAT_INDENT_MORE, MyFrame::OnIndentMore) |
242 | EVT_MENU(ID_FORMAT_INDENT_LESS, MyFrame::OnIndentLess) | |
243 | ||
244 | EVT_MENU(ID_FORMAT_LINE_SPACING_HALF, MyFrame::OnLineSpacingHalf) | |
245 | EVT_MENU(ID_FORMAT_LINE_SPACING_SINGLE, MyFrame::OnLineSpacingSingle) | |
246 | EVT_MENU(ID_FORMAT_LINE_SPACING_DOUBLE, MyFrame::OnLineSpacingDouble) | |
247 | ||
248 | EVT_MENU(ID_FORMAT_PARAGRAPH_SPACING_MORE, MyFrame::OnParagraphSpacingMore) | |
249 | EVT_MENU(ID_FORMAT_PARAGRAPH_SPACING_LESS, MyFrame::OnParagraphSpacingLess) | |
250 | ||
8c9c49a1 JS |
251 | EVT_MENU(ID_INSERT_SYMBOL, MyFrame::OnInsertSymbol) |
252 | ||
5d7836c4 | 253 | EVT_MENU(ID_VIEW_HTML, MyFrame::OnViewHTML) |
fe5aa22c | 254 | EVT_MENU(ID_SWITCH_STYLE_SHEETS, MyFrame::OnSwitchStyleSheets) |
5d7836c4 JS |
255 | END_EVENT_TABLE() |
256 | ||
257 | // Create a new application object: this macro will allow wxWidgets to create | |
258 | // the application object during program execution (it's better than using a | |
259 | // static object for many reasons) and also implements the accessor function | |
260 | // wxGetApp() which will return the reference of the right type (i.e. MyApp and | |
261 | // not wxApp) | |
262 | IMPLEMENT_APP(MyApp) | |
263 | ||
264 | // ============================================================================ | |
265 | // implementation | |
266 | // ============================================================================ | |
267 | ||
268 | // ---------------------------------------------------------------------------- | |
269 | // the application class | |
270 | // ---------------------------------------------------------------------------- | |
271 | ||
272 | // 'Main program' equivalent: the program execution "starts" here | |
273 | bool MyApp::OnInit() | |
274 | { | |
275 | m_styleSheet = new wxRichTextStyleSheet; | |
276 | ||
277 | CreateStyles(); | |
278 | ||
279 | // Add extra handlers (plain text is automatically added) | |
280 | wxRichTextBuffer::AddHandler(new wxRichTextXMLHandler); | |
281 | wxRichTextBuffer::AddHandler(new wxRichTextHTMLHandler); | |
282 | ||
283 | // Add image handlers | |
284 | #if wxUSE_LIBPNG | |
285 | wxImage::AddHandler( new wxPNGHandler ); | |
286 | #endif | |
9a173d48 | 287 | |
5d7836c4 JS |
288 | #if wxUSE_LIBJPEG |
289 | wxImage::AddHandler( new wxJPEGHandler ); | |
290 | #endif | |
291 | ||
292 | #if wxUSE_GIF | |
293 | wxImage::AddHandler( new wxGIFHandler ); | |
294 | #endif | |
295 | ||
296 | // create the main application window | |
ebd90cce | 297 | MyFrame *frame = new MyFrame(_T("wxRichTextCtrl Sample"), wxID_ANY, wxDefaultPosition, wxSize(700, 600)); |
5d7836c4 JS |
298 | |
299 | // and show it (the frames, unlike simple controls, are not shown when | |
300 | // created initially) | |
301 | frame->Show(true); | |
302 | ||
303 | // success: wxApp::OnRun() will be called which will enter the main message | |
304 | // loop and the application will run. If we returned false here, the | |
305 | // application would exit immediately. | |
306 | return true; | |
307 | } | |
308 | ||
309 | int MyApp::OnExit() | |
310 | { | |
311 | delete m_styleSheet; | |
312 | return 0; | |
313 | } | |
314 | ||
315 | void MyApp::CreateStyles() | |
316 | { | |
317 | // Paragraph styles | |
318 | ||
319 | wxFont romanFont(12, wxROMAN, wxNORMAL, wxNORMAL); | |
320 | wxFont swissFont(12, wxSWISS, wxNORMAL, wxNORMAL); | |
321 | ||
322 | wxRichTextParagraphStyleDefinition* normalPara = new wxRichTextParagraphStyleDefinition(wxT("Normal")); | |
323 | wxRichTextAttr normalAttr; | |
324 | normalAttr.SetFontFaceName(romanFont.GetFaceName()); | |
325 | normalAttr.SetFontSize(12); | |
326 | // Let's set all attributes for this style | |
327 | 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| | |
328 | wxTEXT_ATTR_PARA_SPACING_BEFORE|wxTEXT_ATTR_PARA_SPACING_AFTER|wxTEXT_ATTR_LINE_SPACING| | |
329 | wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER); | |
330 | normalPara->SetStyle(normalAttr); | |
9a173d48 | 331 | |
5d7836c4 JS |
332 | m_styleSheet->AddParagraphStyle(normalPara); |
333 | ||
334 | wxRichTextParagraphStyleDefinition* indentedPara = new wxRichTextParagraphStyleDefinition(wxT("Indented")); | |
335 | wxRichTextAttr indentedAttr; | |
336 | indentedAttr.SetFontFaceName(romanFont.GetFaceName()); | |
337 | indentedAttr.SetFontSize(12); | |
338 | indentedAttr.SetLeftIndent(100, 0); | |
339 | // We only want to affect indentation | |
340 | indentedAttr.SetFlags(wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT); | |
341 | indentedPara->SetStyle(indentedAttr); | |
9a173d48 | 342 | |
5d7836c4 JS |
343 | m_styleSheet->AddParagraphStyle(indentedPara); |
344 | ||
27e20452 JS |
345 | wxRichTextParagraphStyleDefinition* indentedPara2 = new wxRichTextParagraphStyleDefinition(wxT("Red Bold Indented")); |
346 | wxRichTextAttr indentedAttr2; | |
347 | indentedAttr2.SetFontFaceName(romanFont.GetFaceName()); | |
348 | indentedAttr2.SetFontSize(12); | |
349 | indentedAttr2.SetFontWeight(wxBOLD); | |
350 | indentedAttr2.SetTextColour(*wxRED); | |
351 | indentedAttr2.SetFontSize(12); | |
352 | indentedAttr2.SetLeftIndent(100, 0); | |
353 | // We want to affect indentation, font and text colour | |
354 | indentedAttr2.SetFlags(wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT|wxTEXT_ATTR_FONT|wxTEXT_ATTR_TEXT_COLOUR); | |
355 | indentedPara2->SetStyle(indentedAttr2); | |
356 | ||
357 | m_styleSheet->AddParagraphStyle(indentedPara2); | |
358 | ||
5d7836c4 JS |
359 | wxRichTextParagraphStyleDefinition* flIndentedPara = new wxRichTextParagraphStyleDefinition(wxT("First Line Indented")); |
360 | wxRichTextAttr flIndentedAttr; | |
361 | flIndentedAttr.SetFontFaceName(swissFont.GetFaceName()); | |
362 | flIndentedAttr.SetFontSize(12); | |
363 | flIndentedAttr.SetLeftIndent(100, -100); | |
364 | // We only want to affect indentation | |
365 | flIndentedAttr.SetFlags(wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT); | |
366 | flIndentedPara->SetStyle(flIndentedAttr); | |
9a173d48 | 367 | |
5d7836c4 JS |
368 | m_styleSheet->AddParagraphStyle(flIndentedPara); |
369 | ||
370 | // Character styles | |
371 | ||
372 | wxRichTextCharacterStyleDefinition* boldDef = new wxRichTextCharacterStyleDefinition(wxT("Bold")); | |
373 | wxRichTextAttr boldAttr; | |
374 | boldAttr.SetFontFaceName(romanFont.GetFaceName()); | |
375 | boldAttr.SetFontSize(12); | |
376 | boldAttr.SetFontWeight(wxBOLD); | |
377 | // We only want to affect boldness | |
378 | boldAttr.SetFlags(wxTEXT_ATTR_FONT_WEIGHT); | |
379 | boldDef->SetStyle(boldAttr); | |
9a173d48 | 380 | |
5d7836c4 JS |
381 | m_styleSheet->AddCharacterStyle(boldDef); |
382 | ||
383 | wxRichTextCharacterStyleDefinition* italicDef = new wxRichTextCharacterStyleDefinition(wxT("Italic")); | |
384 | wxRichTextAttr italicAttr; | |
385 | italicAttr.SetFontFaceName(romanFont.GetFaceName()); | |
386 | italicAttr.SetFontSize(12); | |
387 | italicAttr.SetFontStyle(wxITALIC); | |
388 | // We only want to affect italics | |
389 | italicAttr.SetFlags(wxTEXT_ATTR_FONT_ITALIC); | |
390 | italicDef->SetStyle(italicAttr); | |
9a173d48 | 391 | |
5d7836c4 JS |
392 | m_styleSheet->AddCharacterStyle(italicDef); |
393 | ||
394 | wxRichTextCharacterStyleDefinition* redDef = new wxRichTextCharacterStyleDefinition(wxT("Red Bold")); | |
395 | wxRichTextAttr redAttr; | |
396 | redAttr.SetFontFaceName(romanFont.GetFaceName()); | |
397 | redAttr.SetFontSize(12); | |
398 | redAttr.SetFontWeight(wxBOLD); | |
399 | redAttr.SetTextColour(*wxRED); | |
400 | // We only want to affect colour, weight and face | |
401 | redAttr.SetFlags(wxTEXT_ATTR_FONT_FACE|wxTEXT_ATTR_FONT_WEIGHT|wxTEXT_ATTR_TEXT_COLOUR); | |
402 | redDef->SetStyle(redAttr); | |
9a173d48 | 403 | |
5d7836c4 JS |
404 | m_styleSheet->AddCharacterStyle(redDef); |
405 | } | |
406 | ||
407 | // ---------------------------------------------------------------------------- | |
408 | // main frame | |
409 | // ---------------------------------------------------------------------------- | |
410 | ||
411 | // frame constructor | |
412 | MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos, | |
413 | const wxSize& size, long style) | |
414 | : wxFrame(NULL, id, title, pos, size, style) | |
415 | { | |
416 | // set the frame icon | |
1226b3b3 | 417 | SetIcon(wxICON(sample)); |
5d7836c4 JS |
418 | |
419 | // create a menu bar | |
420 | wxMenu *fileMenu = new wxMenu; | |
421 | ||
422 | // the "About" item should be in the help menu | |
423 | wxMenu *helpMenu = new wxMenu; | |
424 | helpMenu->Append(ID_About, _T("&About...\tF1"), _T("Show about dialog")); | |
425 | ||
426 | fileMenu->Append(wxID_OPEN, _T("&Open\tCtrl+O"), _T("Open a file")); | |
427 | fileMenu->Append(wxID_SAVE, _T("&Save\tCtrl+S"), _T("Save a file")); | |
428 | fileMenu->Append(wxID_SAVEAS, _T("&Save As...\tF12"), _T("Save to a new file")); | |
429 | fileMenu->AppendSeparator(); | |
430 | fileMenu->Append(ID_VIEW_HTML, _T("&View as HTML"), _T("View HTML")); | |
431 | fileMenu->AppendSeparator(); | |
c4cd20cf | 432 | fileMenu->Append(ID_Quit, _T("E&xit\tAlt+X"), _T("Quit this program")); |
5d7836c4 JS |
433 | |
434 | wxMenu* editMenu = new wxMenu; | |
435 | editMenu->Append(wxID_UNDO, _("&Undo\tCtrl+Z")); | |
436 | editMenu->Append(wxID_REDO, _("&Redo\tCtrl+Y")); | |
437 | editMenu->AppendSeparator(); | |
438 | editMenu->Append(wxID_CUT, _("Cu&t\tCtrl+X")); | |
439 | editMenu->Append(wxID_COPY, _("&Copy\tCtrl+C")); | |
440 | editMenu->Append(wxID_PASTE, _("&Paste\tCtrl+V")); | |
441 | ||
442 | editMenu->Append(wxID_CLEAR, _("&Delete\tDel")); | |
443 | ||
444 | editMenu->AppendSeparator(); | |
445 | editMenu->Append(wxID_SELECTALL, _("Select A&ll\tCtrl+A")); | |
446 | #if 0 | |
447 | editMenu->AppendSeparator(); | |
448 | editMenu->Append(wxID_FIND, _("&Find...\tCtrl+F")); | |
449 | editMenu->Append(stID_FIND_REPLACE, _("&Replace...\tCtrl+R")); | |
450 | #endif | |
451 | ||
452 | wxMenu* formatMenu = new wxMenu; | |
453 | formatMenu->AppendCheckItem(ID_FORMAT_BOLD, _("&Bold\tCtrl+B")); | |
454 | formatMenu->AppendCheckItem(ID_FORMAT_ITALIC, _("&Italic\tCtrl+I")); | |
455 | formatMenu->AppendCheckItem(ID_FORMAT_UNDERLINE, _("&Underline\tCtrl+U")); | |
456 | formatMenu->AppendSeparator(); | |
457 | formatMenu->AppendCheckItem(ID_FORMAT_ALIGN_LEFT, _("L&eft Align")); | |
458 | formatMenu->AppendCheckItem(ID_FORMAT_ALIGN_RIGHT, _("&Right Align")); | |
459 | formatMenu->AppendCheckItem(ID_FORMAT_ALIGN_CENTRE, _("&Centre")); | |
460 | formatMenu->AppendSeparator(); | |
c4cd20cf | 461 | formatMenu->Append(ID_FORMAT_INDENT_MORE, _("Indent &More")); |
5d7836c4 JS |
462 | formatMenu->Append(ID_FORMAT_INDENT_LESS, _("Indent &Less")); |
463 | formatMenu->AppendSeparator(); | |
464 | formatMenu->Append(ID_FORMAT_PARAGRAPH_SPACING_MORE, _("Increase Paragraph &Spacing")); | |
465 | formatMenu->Append(ID_FORMAT_PARAGRAPH_SPACING_LESS, _("Decrease &Paragraph Spacing")); | |
466 | formatMenu->AppendSeparator(); | |
467 | formatMenu->Append(ID_FORMAT_LINE_SPACING_SINGLE, _("Normal Line Spacing")); | |
468 | formatMenu->Append(ID_FORMAT_LINE_SPACING_HALF, _("1.5 Line Spacing")); | |
469 | formatMenu->Append(ID_FORMAT_LINE_SPACING_DOUBLE, _("Double Line Spacing")); | |
470 | formatMenu->AppendSeparator(); | |
471 | formatMenu->Append(ID_FORMAT_FONT, _("&Font...")); | |
8c9c49a1 JS |
472 | formatMenu->Append(ID_FORMAT_PARAGRAPH, _("&Paragraph...")); |
473 | formatMenu->Append(ID_FORMAT_CONTENT, _("Font and Pa&ragraph...\tShift+Ctrl+F")); | |
fe5aa22c JS |
474 | formatMenu->AppendSeparator(); |
475 | formatMenu->Append(ID_SWITCH_STYLE_SHEETS, _("&Switch Style Sheets")); | |
5d7836c4 | 476 | |
8c9c49a1 JS |
477 | wxMenu* insertMenu = new wxMenu; |
478 | insertMenu->Append(ID_INSERT_SYMBOL, _("&Symbol...\tCtrl+I")); | |
479 | ||
5d7836c4 JS |
480 | // now append the freshly created menu to the menu bar... |
481 | wxMenuBar *menuBar = new wxMenuBar(); | |
482 | menuBar->Append(fileMenu, _T("&File")); | |
483 | menuBar->Append(editMenu, _T("&Edit")); | |
484 | menuBar->Append(formatMenu, _T("F&ormat")); | |
8c9c49a1 | 485 | menuBar->Append(insertMenu, _T("&Insert")); |
5d7836c4 JS |
486 | menuBar->Append(helpMenu, _T("&Help")); |
487 | ||
488 | // ... and attach this menu bar to the frame | |
489 | SetMenuBar(menuBar); | |
490 | ||
491 | // create a status bar just for fun (by default with 1 pane only) | |
4753c7ce WS |
492 | // but don't create it on limited screen space (WinCE) |
493 | bool is_pda = wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA; | |
494 | ||
9a173d48 | 495 | #if wxUSE_STATUSBAR |
4753c7ce WS |
496 | if ( !is_pda ) |
497 | { | |
498 | CreateStatusBar(2); | |
499 | SetStatusText(_T("Welcome to wxRichTextCtrl!")); | |
500 | } | |
9a173d48 | 501 | #endif |
5d7836c4 JS |
502 | |
503 | wxToolBar* toolBar = CreateToolBar(); | |
504 | ||
9a173d48 WS |
505 | toolBar->AddTool(wxID_OPEN, wxBitmap(open_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Open")); |
506 | toolBar->AddTool(wxID_SAVEAS, wxBitmap(save_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Save")); | |
5d7836c4 | 507 | toolBar->AddSeparator(); |
9a173d48 WS |
508 | toolBar->AddTool(wxID_CUT, wxBitmap(cut_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Cut")); |
509 | toolBar->AddTool(wxID_COPY, wxBitmap(copy_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Copy")); | |
510 | toolBar->AddTool(wxID_PASTE, wxBitmap(paste_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Paste")); | |
5d7836c4 | 511 | toolBar->AddSeparator(); |
9a173d48 WS |
512 | toolBar->AddTool(wxID_UNDO, wxBitmap(undo_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Undo")); |
513 | toolBar->AddTool(wxID_REDO, wxBitmap(redo_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Redo")); | |
5d7836c4 | 514 | toolBar->AddSeparator(); |
9a173d48 WS |
515 | toolBar->AddTool(ID_FORMAT_BOLD, wxBitmap(bold_xpm), wxNullBitmap, true, -1, -1, (wxObject *) NULL, _("Bold")); |
516 | toolBar->AddTool(ID_FORMAT_ITALIC, wxBitmap(italic_xpm), wxNullBitmap, true, -1, -1, (wxObject *) NULL, _("Italic")); | |
517 | toolBar->AddTool(ID_FORMAT_UNDERLINE, wxBitmap(underline_xpm), wxNullBitmap, true, -1, -1, (wxObject *) NULL, _("Underline")); | |
5d7836c4 | 518 | toolBar->AddSeparator(); |
9a173d48 WS |
519 | toolBar->AddTool(ID_FORMAT_ALIGN_LEFT, wxBitmap(alignleft_xpm), wxNullBitmap, true, -1, -1, (wxObject *) NULL, _("Align Left")); |
520 | toolBar->AddTool(ID_FORMAT_ALIGN_CENTRE, wxBitmap(centre_xpm), wxNullBitmap, true, -1, -1, (wxObject *) NULL, _("Centre")); | |
521 | toolBar->AddTool(ID_FORMAT_ALIGN_RIGHT, wxBitmap(alignright_xpm), wxNullBitmap, true, -1, -1, (wxObject *) NULL, _("Align Right")); | |
5d7836c4 | 522 | toolBar->AddSeparator(); |
9a173d48 WS |
523 | toolBar->AddTool(ID_FORMAT_INDENT_LESS, wxBitmap(indentless_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Indent Less")); |
524 | toolBar->AddTool(ID_FORMAT_INDENT_MORE, wxBitmap(indentmore_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Indent More")); | |
5d7836c4 | 525 | toolBar->AddSeparator(); |
9a173d48 | 526 | toolBar->AddTool(ID_FORMAT_FONT, wxBitmap(font_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Font")); |
5d7836c4 | 527 | |
fe5aa22c | 528 | wxRichTextStyleComboCtrl* combo = new wxRichTextStyleComboCtrl(toolBar, ID_RICHTEXT_STYLE_COMBO, wxDefaultPosition, wxSize(200, -1)); |
e637208a JS |
529 | toolBar->AddControl(combo); |
530 | ||
5d7836c4 JS |
531 | toolBar->Realize(); |
532 | ||
c59f6793 | 533 | wxSplitterWindow* splitter = new wxSplitterWindow(this, wxID_ANY, wxDefaultPosition, GetClientSize(), wxSP_NO_XP_THEME|wxSP_3D|wxSP_LIVE_UPDATE); |
5d7836c4 JS |
534 | |
535 | wxFont textFont = wxFont(12, wxROMAN, wxNORMAL, wxNORMAL); | |
536 | wxFont boldFont = wxFont(12, wxROMAN, wxNORMAL, wxBOLD); | |
537 | wxFont italicFont = wxFont(12, wxROMAN, wxITALIC, wxNORMAL); | |
538 | ||
fe5aa22c | 539 | m_richTextCtrl = new wxRichTextCtrl(splitter, ID_RICHTEXT_CTRL, wxEmptyString, wxDefaultPosition, wxSize(200, 200), wxVSCROLL|wxHSCROLL|wxNO_BORDER|wxWANTS_CHARS); |
ff2baa25 JS |
540 | wxFont font(12, wxROMAN, wxNORMAL, wxNORMAL); |
541 | ||
ff2baa25 | 542 | m_richTextCtrl->SetFont(font); |
5d7836c4 | 543 | |
fe5aa22c JS |
544 | m_richTextCtrl->SetStyleSheet(wxGetApp().GetStyleSheet()); |
545 | ||
e637208a JS |
546 | combo->SetStyleSheet(wxGetApp().GetStyleSheet()); |
547 | combo->SetRichTextCtrl(m_richTextCtrl); | |
548 | combo->UpdateStyles(); | |
549 | ||
fe5aa22c | 550 | wxRichTextStyleListBox* styleListBox = new wxRichTextStyleListBox(splitter, ID_RICHTEXT_STYLE_LIST); |
4753c7ce WS |
551 | |
552 | wxSize display = wxGetDisplaySize(); | |
553 | if ( is_pda && ( display.GetWidth() < display.GetHeight() ) ) | |
554 | { | |
555 | splitter->SplitHorizontally(m_richTextCtrl, styleListBox); | |
556 | } | |
557 | else | |
558 | { | |
ebd90cce | 559 | splitter->SplitVertically(m_richTextCtrl, styleListBox, 500); |
4753c7ce | 560 | } |
5d7836c4 | 561 | |
c59f6793 JS |
562 | splitter->UpdateSize(); |
563 | ||
5d7836c4 JS |
564 | styleListBox->SetStyleSheet(wxGetApp().GetStyleSheet()); |
565 | styleListBox->SetRichTextCtrl(m_richTextCtrl); | |
566 | styleListBox->UpdateStyles(); | |
567 | ||
568 | wxRichTextCtrl& r = *m_richTextCtrl; | |
569 | ||
8c9c49a1 JS |
570 | #if 0 |
571 | r.WriteText(wxT("One\nTwo\nThree\n")); | |
572 | #if 0 | |
573 | int i; | |
574 | for (i = 0; i < 3; i++) | |
575 | { | |
576 | ||
577 | wxRichTextParagraph* para = r.GetBuffer().GetParagraphAtLine(i); | |
578 | if (para) | |
579 | { | |
580 | wxLogDebug(wxT("Range for paragraph %d: %d -> %d"), i, para->GetRange().GetStart(), para->GetRange().GetEnd()); | |
581 | } | |
582 | } | |
583 | #endif | |
584 | #else | |
585 | ||
5d7836c4 JS |
586 | r.BeginSuppressUndo(); |
587 | ||
588 | r.BeginParagraphSpacing(0, 20); | |
589 | ||
590 | r.BeginAlignment(wxTEXT_ALIGNMENT_CENTRE); | |
591 | r.BeginBold(); | |
592 | ||
593 | r.BeginFontSize(14); | |
594 | r.WriteText(wxT("Welcome to wxRichTextCtrl, a wxWidgets control for editing and presenting styled text and images")); | |
595 | r.EndFontSize(); | |
596 | r.Newline(); | |
597 | ||
598 | r.BeginItalic(); | |
599 | r.WriteText(wxT("by Julian Smart")); | |
600 | r.EndItalic(); | |
601 | ||
602 | r.EndBold(); | |
603 | ||
604 | r.Newline(); | |
605 | r.WriteImage(wxBitmap(zebra_xpm)); | |
606 | ||
607 | r.EndAlignment(); | |
608 | ||
609 | r.Newline(); | |
610 | r.Newline(); | |
611 | ||
612 | r.WriteText(wxT("What can you do with this thing? ")); | |
613 | r.WriteImage(wxBitmap(smiley_xpm)); | |
614 | r.WriteText(wxT(" Well, you can change text ")); | |
615 | ||
616 | r.BeginTextColour(wxColour(255, 0, 0)); | |
617 | r.WriteText(wxT("colour, like this red bit.")); | |
618 | r.EndTextColour(); | |
619 | ||
620 | r.BeginTextColour(wxColour(0, 0, 255)); | |
621 | r.WriteText(wxT(" And this blue bit.")); | |
622 | r.EndTextColour(); | |
623 | ||
624 | r.WriteText(wxT(" Naturally you can make things ")); | |
625 | r.BeginBold(); | |
626 | r.WriteText(wxT("bold ")); | |
627 | r.EndBold(); | |
628 | r.BeginItalic(); | |
629 | r.WriteText(wxT("or italic ")); | |
630 | r.EndItalic(); | |
631 | r.BeginUnderline(); | |
632 | r.WriteText(wxT("or underlined.")); | |
633 | r.EndUnderline(); | |
634 | ||
635 | r.BeginFontSize(14); | |
636 | r.WriteText(wxT(" Different font sizes on the same line is allowed, too.")); | |
637 | r.EndFontSize(); | |
638 | ||
639 | r.WriteText(wxT(" Next we'll show an indented paragraph.")); | |
640 | ||
641 | r.BeginLeftIndent(60); | |
642 | r.Newline(); | |
643 | ||
644 | 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.")); | |
645 | r.EndLeftIndent(); | |
646 | ||
647 | r.Newline(); | |
648 | ||
649 | r.WriteText(wxT("Next, we'll show a first-line indent, achieved using BeginLeftIndent(100, -40).")); | |
650 | ||
651 | r.BeginLeftIndent(100, -40); | |
652 | r.Newline(); | |
653 | ||
654 | 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.")); | |
655 | r.EndLeftIndent(); | |
656 | ||
657 | r.Newline(); | |
658 | ||
659 | r.WriteText(wxT("Numbered bullets are possible, again using subindents:")); | |
660 | ||
661 | r.BeginNumberedBullet(1, 100, 60); | |
662 | r.Newline(); | |
663 | ||
664 | r.WriteText(wxT("This is my first item. Note that wxRichTextCtrl doesn't automatically do numbering, but this will be added later.")); | |
665 | r.EndNumberedBullet(); | |
666 | ||
667 | r.BeginNumberedBullet(2, 100, 60); | |
668 | r.Newline(); | |
669 | ||
670 | r.WriteText(wxT("This is my second item.")); | |
671 | r.EndNumberedBullet(); | |
672 | ||
673 | r.Newline(); | |
674 | ||
675 | r.WriteText(wxT("The following paragraph is right-indented:")); | |
676 | ||
677 | r.BeginRightIndent(200); | |
678 | r.Newline(); | |
679 | ||
680 | 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.")); | |
681 | r.EndRightIndent(); | |
682 | ||
683 | r.Newline(); | |
684 | ||
685 | r.WriteText(wxT("The following paragraph is right-aligned with 1.5 line spacing:")); | |
686 | ||
687 | r.BeginAlignment(wxTEXT_ALIGNMENT_RIGHT); | |
688 | r.BeginLineSpacing(wxTEXT_ATTR_LINE_SPACING_HALF); | |
689 | r.Newline(); | |
690 | ||
691 | 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.")); | |
692 | r.EndLineSpacing(); | |
693 | r.EndAlignment(); | |
694 | ||
7f0d9d71 JS |
695 | wxArrayInt tabs; |
696 | tabs.Add(400); | |
697 | tabs.Add(600); | |
698 | tabs.Add(800); | |
699 | tabs.Add(1000); | |
700 | wxTextAttrEx attr; | |
701 | attr.SetFlags(wxTEXT_ATTR_TABS); | |
702 | attr.SetTabs(tabs); | |
703 | r.SetDefaultStyle(attr); | |
4753c7ce | 704 | |
7f0d9d71 JS |
705 | r.Newline(); |
706 | r.WriteText(wxT("This line contains tabs:\tFirst tab\tSecond tab\tThird tab")); | |
707 | ||
5d7836c4 JS |
708 | r.Newline(); |
709 | r.WriteText(wxT("Other notable features of wxRichTextCtrl include:")); | |
710 | ||
711 | r.BeginSymbolBullet(wxT('*'), 100, 60); | |
712 | r.Newline(); | |
713 | r.WriteText(wxT("Compatibility with wxTextCtrl API")); | |
714 | r.EndSymbolBullet(); | |
715 | ||
716 | r.BeginSymbolBullet(wxT('*'), 100, 60); | |
717 | r.Newline(); | |
718 | r.WriteText(wxT("Easy stack-based BeginXXX()...EndXXX() style setting in addition to SetStyle()")); | |
719 | r.EndSymbolBullet(); | |
720 | ||
721 | r.BeginSymbolBullet(wxT('*'), 100, 60); | |
722 | r.Newline(); | |
723 | r.WriteText(wxT("XML loading and saving")); | |
724 | r.EndSymbolBullet(); | |
725 | ||
726 | r.BeginSymbolBullet(wxT('*'), 100, 60); | |
727 | r.Newline(); | |
728 | r.WriteText(wxT("Undo/Redo, with batching option and Undo suppressing")); | |
729 | r.EndSymbolBullet(); | |
730 | ||
731 | r.BeginSymbolBullet(wxT('*'), 100, 60); | |
732 | r.Newline(); | |
733 | r.WriteText(wxT("Clipboard copy and paste")); | |
734 | r.EndSymbolBullet(); | |
735 | ||
736 | r.BeginSymbolBullet(wxT('*'), 100, 60); | |
737 | r.Newline(); | |
738 | r.WriteText(wxT("wxRichTextStyleSheet with named character and paragraph styles, and control for applying named styles")); | |
739 | r.EndSymbolBullet(); | |
740 | ||
741 | r.BeginSymbolBullet(wxT('*'), 100, 60); | |
742 | r.Newline(); | |
743 | r.WriteText(wxT("A design that can easily be extended to other content types, ultimately with text boxes, tables, controls, and so on")); | |
744 | r.EndSymbolBullet(); | |
745 | ||
746 | r.Newline(); | |
747 | ||
748 | 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!")); | |
749 | ||
750 | r.EndParagraphSpacing(); | |
751 | ||
752 | r.EndSuppressUndo(); | |
8c9c49a1 | 753 | #endif |
5d7836c4 JS |
754 | } |
755 | ||
756 | ||
757 | // event handlers | |
758 | ||
759 | void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) | |
760 | { | |
761 | // true is to force the frame to close | |
762 | Close(true); | |
763 | } | |
764 | ||
765 | void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) | |
766 | { | |
767 | wxString msg; | |
768 | msg.Printf( _T("This is a demo for wxRichTextCtrl, a control for editing styled text.\n(c) Julian Smart, 2005")); | |
769 | wxMessageBox(msg, _T("About wxRichTextCtrl Sample"), wxOK | wxICON_INFORMATION, this); | |
770 | } | |
771 | ||
772 | // Forward command events to the current rich text control, if any | |
773 | bool MyFrame::ProcessEvent(wxEvent& event) | |
774 | { | |
775 | if (event.IsCommandEvent() && !event.IsKindOf(CLASSINFO(wxChildFocusEvent))) | |
776 | { | |
777 | // Problem: we can get infinite recursion because the events | |
778 | // climb back up to this frame, and repeat. | |
779 | // Assume that command events don't cause another command event | |
780 | // to be called, so we can rely on inCommand not being overwritten | |
781 | ||
782 | static int s_eventType = 0; | |
783 | static wxWindowID s_id = 0; | |
784 | ||
785 | if (s_id != event.GetId() && s_eventType != event.GetEventType()) | |
786 | { | |
787 | s_eventType = event.GetEventType(); | |
788 | s_id = event.GetId(); | |
9a173d48 | 789 | |
5d7836c4 JS |
790 | wxWindow* focusWin = wxFindFocusDescendant(this); |
791 | if (focusWin && focusWin->ProcessEvent(event)) | |
792 | { | |
793 | //s_command = NULL; | |
794 | s_eventType = 0; | |
795 | s_id = 0; | |
9a173d48 | 796 | return true; |
5d7836c4 JS |
797 | } |
798 | ||
799 | s_eventType = 0; | |
800 | s_id = 0; | |
801 | } | |
802 | else | |
803 | { | |
9a173d48 | 804 | return false; |
5d7836c4 JS |
805 | } |
806 | } | |
807 | ||
808 | return wxFrame::ProcessEvent(event); | |
809 | } | |
810 | ||
011b3dcb | 811 | void MyFrame::OnOpen(wxCommandEvent& WXUNUSED(event)) |
5d7836c4 | 812 | { |
9a173d48 WS |
813 | wxString path; |
814 | wxString filename; | |
1e967276 JS |
815 | wxArrayInt fileTypes; |
816 | ||
817 | wxString filter = wxRichTextBuffer::GetExtWildcard(false, false, & fileTypes); | |
9a173d48 | 818 | if (!filter.empty()) |
5d7836c4 JS |
819 | filter += wxT("|"); |
820 | filter += wxT("All files (*.*)|*.*"); | |
821 | ||
5d7836c4 JS |
822 | wxFileDialog dialog(this, |
823 | _("Choose a filename"), | |
824 | path, | |
825 | filename, | |
826 | filter, | |
ff3e84ff | 827 | wxFD_OPEN); |
5d7836c4 JS |
828 | |
829 | if (dialog.ShowModal() == wxID_OK) | |
830 | { | |
831 | wxString path = dialog.GetPath(); | |
9a173d48 WS |
832 | |
833 | if (!path.empty()) | |
5d7836c4 | 834 | { |
1e967276 | 835 | int filterIndex = dialog.GetFilterIndex(); |
dbf38e88 WS |
836 | int fileType = (filterIndex < (int) fileTypes.GetCount()) |
837 | ? fileTypes[filterIndex] | |
838 | : wxRICHTEXT_TYPE_TEXT; | |
1e967276 | 839 | m_richTextCtrl->LoadFile(path, fileType); |
5d7836c4 JS |
840 | } |
841 | } | |
842 | } | |
843 | ||
844 | void MyFrame::OnSave(wxCommandEvent& event) | |
845 | { | |
9a173d48 | 846 | if (m_richTextCtrl->GetFilename().empty()) |
5d7836c4 JS |
847 | { |
848 | OnSaveAs(event); | |
849 | return; | |
850 | } | |
851 | m_richTextCtrl->SaveFile(); | |
852 | } | |
853 | ||
011b3dcb | 854 | void MyFrame::OnSaveAs(wxCommandEvent& WXUNUSED(event)) |
5d7836c4 JS |
855 | { |
856 | wxString filter = wxRichTextBuffer::GetExtWildcard(false, true); | |
9a173d48 WS |
857 | wxString path; |
858 | wxString filename; | |
5d7836c4 JS |
859 | |
860 | wxFileDialog dialog(this, | |
861 | _("Choose a filename"), | |
862 | path, | |
863 | filename, | |
864 | filter, | |
ff3e84ff | 865 | wxFD_SAVE); |
5d7836c4 JS |
866 | |
867 | if (dialog.ShowModal() == wxID_OK) | |
868 | { | |
869 | wxString path = dialog.GetPath(); | |
9a173d48 WS |
870 | |
871 | if (!path.empty()) | |
5d7836c4 JS |
872 | { |
873 | m_richTextCtrl->SaveFile(path); | |
874 | } | |
875 | } | |
876 | } | |
877 | ||
011b3dcb | 878 | void MyFrame::OnBold(wxCommandEvent& WXUNUSED(event)) |
5d7836c4 JS |
879 | { |
880 | m_richTextCtrl->ApplyBoldToSelection(); | |
881 | } | |
882 | ||
011b3dcb | 883 | void MyFrame::OnItalic(wxCommandEvent& WXUNUSED(event)) |
5d7836c4 JS |
884 | { |
885 | m_richTextCtrl->ApplyItalicToSelection(); | |
886 | } | |
887 | ||
011b3dcb | 888 | void MyFrame::OnUnderline(wxCommandEvent& WXUNUSED(event)) |
5d7836c4 JS |
889 | { |
890 | m_richTextCtrl->ApplyUnderlineToSelection(); | |
891 | } | |
892 | ||
893 | ||
894 | void MyFrame::OnUpdateBold(wxUpdateUIEvent& event) | |
895 | { | |
896 | event.Check(m_richTextCtrl->IsSelectionBold()); | |
897 | } | |
898 | ||
899 | void MyFrame::OnUpdateItalic(wxUpdateUIEvent& event) | |
900 | { | |
901 | event.Check(m_richTextCtrl->IsSelectionItalics()); | |
902 | } | |
903 | ||
904 | void MyFrame::OnUpdateUnderline(wxUpdateUIEvent& event) | |
905 | { | |
906 | event.Check(m_richTextCtrl->IsSelectionUnderlined()); | |
907 | } | |
908 | ||
011b3dcb | 909 | void MyFrame::OnAlignLeft(wxCommandEvent& WXUNUSED(event)) |
5d7836c4 JS |
910 | { |
911 | m_richTextCtrl->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_LEFT); | |
912 | } | |
913 | ||
011b3dcb | 914 | void MyFrame::OnAlignCentre(wxCommandEvent& WXUNUSED(event)) |
5d7836c4 JS |
915 | { |
916 | m_richTextCtrl->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_CENTRE); | |
917 | } | |
918 | ||
011b3dcb | 919 | void MyFrame::OnAlignRight(wxCommandEvent& WXUNUSED(event)) |
5d7836c4 JS |
920 | { |
921 | m_richTextCtrl->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_RIGHT); | |
922 | } | |
923 | ||
924 | void MyFrame::OnUpdateAlignLeft(wxUpdateUIEvent& event) | |
925 | { | |
926 | event.Check(m_richTextCtrl->IsSelectionAligned(wxTEXT_ALIGNMENT_LEFT)); | |
927 | } | |
928 | ||
929 | void MyFrame::OnUpdateAlignCentre(wxUpdateUIEvent& event) | |
930 | { | |
931 | event.Check(m_richTextCtrl->IsSelectionAligned(wxTEXT_ALIGNMENT_CENTRE)); | |
932 | } | |
933 | ||
934 | void MyFrame::OnUpdateAlignRight(wxUpdateUIEvent& event) | |
935 | { | |
936 | event.Check(m_richTextCtrl->IsSelectionAligned(wxTEXT_ALIGNMENT_RIGHT)); | |
937 | } | |
938 | ||
011b3dcb | 939 | void MyFrame::OnFont(wxCommandEvent& WXUNUSED(event)) |
5d7836c4 | 940 | { |
8c9c49a1 JS |
941 | wxRichTextRange range; |
942 | if (m_richTextCtrl->HasSelection()) | |
943 | range = m_richTextCtrl->GetSelectionRange(); | |
944 | else | |
945 | range = wxRichTextRange(0, m_richTextCtrl->GetLastPosition()+1); | |
946 | ||
947 | int pages = wxRICHTEXT_FORMAT_FONT; | |
948 | ||
949 | wxRichTextFormattingDialog formatDlg(pages, this); | |
950 | formatDlg.GetStyle(m_richTextCtrl, range); | |
951 | ||
952 | if (formatDlg.ShowModal() == wxID_OK) | |
953 | { | |
954 | formatDlg.ApplyStyle(m_richTextCtrl, range); | |
955 | } | |
956 | ||
957 | // Old method using wxFontDialog | |
958 | #if 0 | |
5d7836c4 JS |
959 | if (!m_richTextCtrl->HasSelection()) |
960 | return; | |
961 | ||
962 | wxRichTextRange range = m_richTextCtrl->GetSelectionRange(); | |
963 | wxFontData fontData; | |
964 | ||
965 | wxTextAttrEx attr; | |
966 | attr.SetFlags(wxTEXT_ATTR_FONT); | |
967 | ||
968 | if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr)) | |
969 | fontData.SetInitialFont(attr.GetFont()); | |
970 | ||
971 | wxFontDialog dialog(this, fontData); | |
972 | if (dialog.ShowModal() == wxID_OK) | |
973 | { | |
974 | fontData = dialog.GetFontData(); | |
975 | attr.SetFlags(wxTEXT_ATTR_FONT); | |
976 | attr.SetFont(fontData.GetChosenFont()); | |
977 | if (attr.GetFont().Ok()) | |
978 | { | |
979 | m_richTextCtrl->SetStyle(range, attr); | |
980 | } | |
981 | } | |
8c9c49a1 JS |
982 | #endif |
983 | } | |
984 | ||
985 | void MyFrame::OnParagraph(wxCommandEvent& WXUNUSED(event)) | |
986 | { | |
987 | wxRichTextRange range; | |
988 | if (m_richTextCtrl->HasSelection()) | |
989 | range = m_richTextCtrl->GetSelectionRange(); | |
990 | else | |
991 | range = wxRichTextRange(0, m_richTextCtrl->GetLastPosition()+1); | |
992 | ||
993 | int pages = wxRICHTEXT_FORMAT_INDENTS_SPACING|wxRICHTEXT_FORMAT_TABS|wxRICHTEXT_FORMAT_BULLETS; | |
994 | ||
995 | wxRichTextFormattingDialog formatDlg(pages, this); | |
996 | formatDlg.GetStyle(m_richTextCtrl, range); | |
997 | ||
998 | if (formatDlg.ShowModal() == wxID_OK) | |
999 | { | |
1000 | formatDlg.ApplyStyle(m_richTextCtrl, range); | |
1001 | } | |
1002 | } | |
1003 | ||
1004 | void MyFrame::OnFormat(wxCommandEvent& WXUNUSED(event)) | |
1005 | { | |
1006 | wxRichTextRange range; | |
1007 | if (m_richTextCtrl->HasSelection()) | |
1008 | range = m_richTextCtrl->GetSelectionRange(); | |
1009 | else | |
1010 | range = wxRichTextRange(0, m_richTextCtrl->GetLastPosition()+1); | |
1011 | ||
1012 | int pages = wxRICHTEXT_FORMAT_FONT|wxRICHTEXT_FORMAT_INDENTS_SPACING|wxRICHTEXT_FORMAT_TABS|wxRICHTEXT_FORMAT_BULLETS; | |
1013 | ||
1014 | wxRichTextFormattingDialog formatDlg(pages, this); | |
1015 | formatDlg.GetStyle(m_richTextCtrl, range); | |
1016 | ||
1017 | if (formatDlg.ShowModal() == wxID_OK) | |
1018 | { | |
1019 | formatDlg.ApplyStyle(m_richTextCtrl, range); | |
1020 | } | |
1021 | } | |
1022 | ||
1023 | void MyFrame::OnUpdateFormat(wxUpdateUIEvent& event) | |
1024 | { | |
1025 | event.Enable(m_richTextCtrl->HasSelection()); | |
5d7836c4 JS |
1026 | } |
1027 | ||
011b3dcb | 1028 | void MyFrame::OnIndentMore(wxCommandEvent& WXUNUSED(event)) |
5d7836c4 JS |
1029 | { |
1030 | wxTextAttrEx attr; | |
1031 | attr.SetFlags(wxTEXT_ATTR_LEFT_INDENT); | |
1032 | ||
1033 | if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr)) | |
1034 | { | |
1035 | wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint()); | |
1036 | if (m_richTextCtrl->HasSelection()) | |
1037 | range = m_richTextCtrl->GetSelectionRange(); | |
1038 | ||
1039 | wxFontData fontData; | |
1040 | attr.SetLeftIndent(attr.GetLeftIndent() + 100); | |
1041 | ||
1042 | attr.SetFlags(wxTEXT_ATTR_LEFT_INDENT); | |
1043 | m_richTextCtrl->SetStyle(range, attr); | |
1044 | } | |
1045 | } | |
1046 | ||
011b3dcb | 1047 | void MyFrame::OnIndentLess(wxCommandEvent& WXUNUSED(event)) |
5d7836c4 JS |
1048 | { |
1049 | wxTextAttrEx attr; | |
1050 | attr.SetFlags(wxTEXT_ATTR_LEFT_INDENT); | |
1051 | ||
1052 | if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr)) | |
1053 | { | |
1054 | wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint()); | |
1055 | if (m_richTextCtrl->HasSelection()) | |
1056 | range = m_richTextCtrl->GetSelectionRange(); | |
1057 | ||
1058 | if (attr.GetLeftIndent() >= 100) | |
1059 | { | |
1060 | wxFontData fontData; | |
1061 | attr.SetLeftIndent(attr.GetLeftIndent() - 100); | |
9a173d48 | 1062 | |
5d7836c4 JS |
1063 | m_richTextCtrl->SetStyle(range, attr); |
1064 | } | |
1065 | } | |
1066 | } | |
1067 | ||
011b3dcb | 1068 | void MyFrame::OnLineSpacingHalf(wxCommandEvent& WXUNUSED(event)) |
5d7836c4 JS |
1069 | { |
1070 | wxTextAttrEx attr; | |
1071 | attr.SetFlags(wxTEXT_ATTR_LINE_SPACING); | |
1072 | ||
1073 | if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr)) | |
1074 | { | |
1075 | wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint()); | |
1076 | if (m_richTextCtrl->HasSelection()) | |
1077 | range = m_richTextCtrl->GetSelectionRange(); | |
1078 | ||
1079 | wxFontData fontData; | |
1080 | attr.SetFlags(wxTEXT_ATTR_LINE_SPACING); | |
1081 | attr.SetLineSpacing(15); | |
9a173d48 | 1082 | |
5d7836c4 JS |
1083 | m_richTextCtrl->SetStyle(range, attr); |
1084 | } | |
1085 | } | |
1086 | ||
011b3dcb | 1087 | void MyFrame::OnLineSpacingDouble(wxCommandEvent& WXUNUSED(event)) |
5d7836c4 JS |
1088 | { |
1089 | wxTextAttrEx attr; | |
1090 | attr.SetFlags(wxTEXT_ATTR_LINE_SPACING); | |
1091 | ||
1092 | if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr)) | |
1093 | { | |
1094 | wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint()); | |
1095 | if (m_richTextCtrl->HasSelection()) | |
1096 | range = m_richTextCtrl->GetSelectionRange(); | |
1097 | ||
1098 | wxFontData fontData; | |
1099 | attr.SetFlags(wxTEXT_ATTR_LINE_SPACING); | |
1100 | attr.SetLineSpacing(20); | |
9a173d48 | 1101 | |
5d7836c4 JS |
1102 | m_richTextCtrl->SetStyle(range, attr); |
1103 | } | |
1104 | } | |
1105 | ||
011b3dcb | 1106 | void MyFrame::OnLineSpacingSingle(wxCommandEvent& WXUNUSED(event)) |
5d7836c4 JS |
1107 | { |
1108 | wxTextAttrEx attr; | |
1109 | attr.SetFlags(wxTEXT_ATTR_LINE_SPACING); | |
1110 | ||
1111 | if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr)) | |
1112 | { | |
1113 | wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint()); | |
1114 | if (m_richTextCtrl->HasSelection()) | |
1115 | range = m_richTextCtrl->GetSelectionRange(); | |
1116 | ||
1117 | wxFontData fontData; | |
1118 | attr.SetFlags(wxTEXT_ATTR_LINE_SPACING); | |
1119 | attr.SetLineSpacing(0); // Can also use 10 | |
9a173d48 | 1120 | |
5d7836c4 JS |
1121 | m_richTextCtrl->SetStyle(range, attr); |
1122 | } | |
1123 | } | |
1124 | ||
011b3dcb | 1125 | void MyFrame::OnParagraphSpacingMore(wxCommandEvent& WXUNUSED(event)) |
5d7836c4 JS |
1126 | { |
1127 | wxTextAttrEx attr; | |
1128 | attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER); | |
1129 | ||
1130 | if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr)) | |
1131 | { | |
1132 | wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint()); | |
1133 | if (m_richTextCtrl->HasSelection()) | |
1134 | range = m_richTextCtrl->GetSelectionRange(); | |
1135 | ||
1136 | wxFontData fontData; | |
1137 | attr.SetParagraphSpacingAfter(attr.GetParagraphSpacingAfter() + 20); | |
1138 | ||
1139 | attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER); | |
1140 | m_richTextCtrl->SetStyle(range, attr); | |
1141 | } | |
1142 | } | |
1143 | ||
011b3dcb | 1144 | void MyFrame::OnParagraphSpacingLess(wxCommandEvent& WXUNUSED(event)) |
5d7836c4 JS |
1145 | { |
1146 | wxTextAttrEx attr; | |
1147 | attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER); | |
1148 | ||
1149 | if (m_richTextCtrl->GetStyle(m_richTextCtrl->GetInsertionPoint(), attr)) | |
1150 | { | |
1151 | wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint()); | |
1152 | if (m_richTextCtrl->HasSelection()) | |
1153 | range = m_richTextCtrl->GetSelectionRange(); | |
1154 | ||
1155 | if (attr.GetParagraphSpacingAfter() >= 20) | |
1156 | { | |
1157 | wxFontData fontData; | |
1158 | attr.SetParagraphSpacingAfter(attr.GetParagraphSpacingAfter() - 20); | |
9a173d48 | 1159 | |
5d7836c4 JS |
1160 | attr.SetFlags(wxTEXT_ATTR_PARA_SPACING_AFTER); |
1161 | m_richTextCtrl->SetStyle(range, attr); | |
1162 | } | |
1163 | } | |
1164 | } | |
1165 | ||
011b3dcb | 1166 | void MyFrame::OnViewHTML(wxCommandEvent& WXUNUSED(event)) |
5d7836c4 JS |
1167 | { |
1168 | wxDialog dialog(this, wxID_ANY, _("HTML"), wxDefaultPosition, wxSize(500, 400), wxDEFAULT_DIALOG_STYLE); | |
1169 | ||
1170 | wxBoxSizer* boxSizer = new wxBoxSizer(wxVERTICAL); | |
1171 | dialog.SetSizer(boxSizer); | |
1172 | ||
1173 | wxHtmlWindow* win = new wxHtmlWindow(& dialog, wxID_ANY, wxDefaultPosition, wxSize(500, 400), wxSUNKEN_BORDER); | |
1174 | boxSizer->Add(win, 1, wxALL, 5); | |
1175 | ||
1176 | wxButton* cancelButton = new wxButton(& dialog, wxID_CANCEL, wxT("&Close")); | |
1177 | boxSizer->Add(cancelButton, 0, wxALL|wxCENTRE, 5); | |
1178 | ||
1179 | wxString text; | |
1180 | wxStringOutputStream strStream(& text); | |
1181 | ||
1182 | wxRichTextHTMLHandler htmlHandler; | |
1183 | if (htmlHandler.SaveFile(& m_richTextCtrl->GetBuffer(), strStream)) | |
1184 | { | |
1185 | win->SetPage(text); | |
1186 | } | |
1187 | ||
1188 | boxSizer->Fit(& dialog); | |
1189 | ||
1190 | dialog.ShowModal(); | |
1191 | } | |
fe5aa22c JS |
1192 | |
1193 | // Demonstrates how you can change the style sheets and have the changes | |
1194 | // reflected in the control content without wiping out character formatting. | |
1195 | ||
1196 | void MyFrame::OnSwitchStyleSheets(wxCommandEvent& WXUNUSED(event)) | |
1197 | { | |
1198 | static wxRichTextStyleSheet* gs_AlternateStyleSheet = NULL; | |
1199 | ||
1200 | wxRichTextCtrl* ctrl = (wxRichTextCtrl*) FindWindow(ID_RICHTEXT_CTRL); | |
1201 | wxRichTextStyleListBox* styleList = (wxRichTextStyleListBox*) FindWindow(ID_RICHTEXT_STYLE_LIST); | |
1202 | wxRichTextStyleComboCtrl* styleCombo = (wxRichTextStyleComboCtrl*) FindWindow(ID_RICHTEXT_STYLE_COMBO); | |
1203 | ||
1204 | wxRichTextStyleSheet* sheet = ctrl->GetStyleSheet(); | |
1205 | ||
1206 | // One-time creation of an alternate style sheet | |
1207 | if (!gs_AlternateStyleSheet) | |
1208 | { | |
1209 | gs_AlternateStyleSheet = new wxRichTextStyleSheet(*sheet); | |
1210 | ||
1211 | // Make some modifications | |
1212 | for (int i = 0; i < (int) gs_AlternateStyleSheet->GetParagraphStyleCount(); i++) | |
1213 | { | |
1214 | wxRichTextParagraphStyleDefinition* def = gs_AlternateStyleSheet->GetParagraphStyle(i); | |
1215 | ||
1216 | if (def->GetStyle().HasTextColour()) | |
1217 | def->GetStyle().SetTextColour(*wxBLUE); | |
1218 | ||
1219 | if (def->GetStyle().HasAlignment()) | |
1220 | { | |
1221 | if (def->GetStyle().GetAlignment() == wxTEXT_ALIGNMENT_CENTRE) | |
1222 | def->GetStyle().SetAlignment(wxTEXT_ALIGNMENT_RIGHT); | |
1223 | else if (def->GetStyle().GetAlignment() == wxTEXT_ALIGNMENT_LEFT) | |
1224 | def->GetStyle().SetAlignment(wxTEXT_ALIGNMENT_CENTRE); | |
1225 | } | |
1226 | if (def->GetStyle().HasLeftIndent()) | |
1227 | { | |
1228 | def->GetStyle().SetLeftIndent(def->GetStyle().GetLeftIndent() * 2); | |
1229 | } | |
1230 | } | |
1231 | } | |
1232 | ||
1233 | // Switch sheets | |
1234 | wxRichTextStyleSheet* tmp = gs_AlternateStyleSheet; | |
1235 | gs_AlternateStyleSheet = sheet; | |
1236 | sheet = tmp; | |
1237 | ||
1238 | ctrl->SetStyleSheet(sheet); | |
1239 | ctrl->ApplyStyleSheet(sheet); // Makes the control reflect the new style definitions | |
1240 | ||
1241 | styleList->SetStyleSheet(sheet); | |
1242 | styleList->UpdateStyles(); | |
1243 | ||
1244 | styleCombo->SetStyleSheet(sheet); | |
1245 | styleCombo->UpdateStyles(); | |
1246 | } | |
8c9c49a1 JS |
1247 | |
1248 | void MyFrame::OnInsertSymbol(wxCommandEvent& WXUNUSED(event)) | |
1249 | { | |
1250 | wxRichTextCtrl* ctrl = (wxRichTextCtrl*) FindWindow(ID_RICHTEXT_CTRL); | |
1251 | ||
1252 | wxTextAttrEx attr; | |
1253 | attr.SetFlags(wxTEXT_ATTR_FONT); | |
1254 | ctrl->GetStyle(ctrl->GetInsertionPoint(), attr); | |
1255 | ||
1256 | wxString currentFontName; | |
1257 | if (attr.HasFont() && attr.GetFont().Ok()) | |
1258 | currentFontName = attr.GetFont().GetFaceName(); | |
1259 | ||
1260 | // Don't set the initial font in the dialog (so the user is choosing | |
1261 | // 'normal text', i.e. the current font) but do tell the dialog | |
1262 | // what 'normal text' is. | |
1263 | ||
1264 | wxSymbolPickerDialog dlg(wxT("*"), wxEmptyString, currentFontName, this); | |
1265 | ||
1266 | if (dlg.ShowModal() == wxID_OK) | |
1267 | { | |
1268 | if (dlg.HasSelection()) | |
1269 | { | |
1270 | long insertionPoint = ctrl->GetInsertionPoint(); | |
1271 | ||
1272 | ctrl->WriteText(dlg.GetSymbol()); | |
1273 | ||
1274 | if (!dlg.UseNormalFont()) | |
1275 | { | |
1276 | wxFont font(attr.GetFont()); | |
1277 | font.SetFaceName(dlg.GetNormalTextFontName()); | |
1278 | attr.SetFont(font); | |
1279 | ctrl->SetStyle(insertionPoint, insertionPoint+1, attr); | |
1280 | } | |
1281 | } | |
1282 | } | |
1283 | } |