Applied #12941: Fixes and enhancements for wxRTC (Robert Hoffman)
[wxWidgets.git] / src / richtext / richtextformatdlg.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/richtext/richtextformatdlg.cpp
3 // Purpose: Formatting dialog for wxRichTextCtrl
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 2006-10-01
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #if wxUSE_RICHTEXT
20
21 #include "wx/richtext/richtextformatdlg.h"
22
23 #ifndef WX_PRECOMP
24 #include "wx/listbox.h"
25 #include "wx/combobox.h"
26 #include "wx/textctrl.h"
27 #include "wx/sizer.h"
28 #include "wx/stattext.h"
29 #include "wx/statline.h"
30 #include "wx/radiobut.h"
31 #include "wx/icon.h"
32 #include "wx/bitmap.h"
33 #include "wx/dcclient.h"
34 #include "wx/frame.h"
35 #include "wx/checkbox.h"
36 #include "wx/button.h"
37 #endif // WX_PRECOMP
38
39 #include "wx/bookctrl.h"
40 #include "wx/colordlg.h"
41 #include "wx/settings.h"
42 #include "wx/module.h"
43 #include "wx/imaglist.h"
44
45 #include "wx/richtext/richtextctrl.h"
46 #include "wx/richtext/richtextstyles.h"
47
48 #ifdef __WXMAC__
49 #include "../../src/richtext/richtextfontpage.cpp"
50 #include "../../src/richtext/richtextindentspage.cpp"
51 #include "../../src/richtext/richtexttabspage.cpp"
52 #include "../../src/richtext/richtextbulletspage.cpp"
53 #include "../../src/richtext/richtextstylepage.cpp"
54 #include "../../src/richtext/richtextliststylepage.cpp"
55 #include "../../src/richtext/richtextsizepage.cpp"
56 #include "../../src/richtext/richtextmarginspage.cpp"
57 #include "../../src/richtext/richtextborderspage.cpp"
58 #include "../../src/richtext/richtextbackgroundpage.cpp"
59 #else
60 #include "richtextfontpage.cpp"
61 #include "richtextindentspage.cpp"
62 #include "richtexttabspage.cpp"
63 #include "richtextbulletspage.cpp"
64 #include "richtextmarginspage.cpp"
65 #include "richtextsizepage.cpp"
66 #include "richtextborderspage.cpp"
67 #include "richtextbackgroundpage.cpp"
68 // Digital Mars can't cope with this much code
69 #ifndef __DMC__
70 #include "richtextliststylepage.cpp"
71 #endif
72 #include "richtextstylepage.cpp"
73 #endif
74
75 #if 0 // def __WXMAC__
76 #define wxRICHTEXT_USE_TOOLBOOK 1
77 #else
78 #define wxRICHTEXT_USE_TOOLBOOK 0
79 #endif
80
81 bool wxRichTextFormattingDialog::sm_showToolTips = false;
82
83 IMPLEMENT_CLASS(wxRichTextFormattingDialog, wxPropertySheetDialog)
84
85 BEGIN_EVENT_TABLE(wxRichTextFormattingDialog, wxPropertySheetDialog)
86 EVT_BOOKCTRL_PAGE_CHANGED(wxID_ANY, wxRichTextFormattingDialog::OnTabChanged)
87 EVT_BUTTON(wxID_HELP, wxRichTextFormattingDialog::OnHelp)
88 EVT_UPDATE_UI(wxID_HELP, wxRichTextFormattingDialog::OnUpdateHelp)
89 END_EVENT_TABLE()
90
91 IMPLEMENT_HELP_PROVISION(wxRichTextFormattingDialog)
92
93 wxRichTextFormattingDialogFactory* wxRichTextFormattingDialog::ms_FormattingDialogFactory = NULL;
94
95 void wxRichTextFormattingDialog::Init()
96 {
97 m_imageList = NULL;
98 m_styleDefinition = NULL;
99 m_styleSheet = NULL;
100 m_object = NULL;
101 }
102
103 wxRichTextFormattingDialog::~wxRichTextFormattingDialog()
104 {
105 delete m_imageList;
106 delete m_styleDefinition;
107 }
108
109 bool wxRichTextFormattingDialog::Create(long flags, wxWindow* parent, const wxString& title, wxWindowID id,
110 const wxPoint& pos, const wxSize& sz, long style)
111 {
112 SetExtraStyle(wxDIALOG_EX_CONTEXTHELP|wxWS_EX_VALIDATE_RECURSIVELY);
113
114 int resizeBorder = wxRESIZE_BORDER;
115
116 GetFormattingDialogFactory()->SetSheetStyle(this);
117
118 wxPropertySheetDialog::Create(parent, id, title, pos, sz,
119 style | (int)wxPlatform::IfNot(wxOS_WINDOWS_CE, resizeBorder)
120 );
121
122 GetFormattingDialogFactory()->CreateButtons(this);
123 GetFormattingDialogFactory()->CreatePages(flags, this);
124
125 LayoutDialog();
126
127 return true;
128 }
129
130 /// Get attributes from the given range
131 bool wxRichTextFormattingDialog::GetStyle(wxRichTextCtrl* ctrl, const wxRichTextRange& range)
132 {
133 if (ctrl->GetFocusObject()->GetStyleForRange(range.ToInternal(), m_attributes))
134 return UpdateDisplay();
135 else
136 return false;
137 }
138
139 /// Apply attributes to the given range, only applying if necessary (wxRICHTEXT_SETSTYLE_OPTIMIZE)
140 bool wxRichTextFormattingDialog::ApplyStyle(wxRichTextCtrl* ctrl, const wxRichTextRange& range, int flags)
141 {
142 return ctrl->SetStyleEx(range, m_attributes, flags);
143 }
144
145 // Apply attributes to the object being edited, if any
146 bool wxRichTextFormattingDialog::ApplyStyle(wxRichTextCtrl* WXUNUSED(ctrl), int flags)
147 {
148 if (GetObject())
149 {
150 wxRichTextParagraphLayoutBox* parentContainer = GetObject()->GetParentContainer();
151 if (parentContainer)
152 parentContainer->SetStyle(GetObject(), m_attributes, flags);
153 return true;
154 }
155 else
156 return false;
157 }
158
159 /// Set the attributes and optionally update the display
160 bool wxRichTextFormattingDialog::SetStyle(const wxRichTextAttr& style, bool update)
161 {
162 m_attributes = style;
163 if (update)
164 UpdateDisplay();
165 return true;
166 }
167
168 /// Set the style definition and optionally update the display
169 bool wxRichTextFormattingDialog::SetStyleDefinition(const wxRichTextStyleDefinition& styleDef, wxRichTextStyleSheet* sheet, bool update)
170 {
171 m_styleSheet = sheet;
172
173 if (m_styleDefinition)
174 delete m_styleDefinition;
175 m_styleDefinition = styleDef.Clone();
176
177 return SetStyle(m_styleDefinition->GetStyle(), update);
178 }
179
180 /// Transfers the data and from to the window
181 bool wxRichTextFormattingDialog::TransferDataToWindow()
182 {
183 if (m_styleDefinition)
184 m_attributes = m_styleDefinition->GetStyle();
185
186 if (!wxPropertySheetDialog::TransferDataToWindow())
187 return false;
188
189 return true;
190 }
191
192 bool wxRichTextFormattingDialog::TransferDataFromWindow()
193 {
194 if (!wxPropertySheetDialog::TransferDataFromWindow())
195 return false;
196
197 if (m_styleDefinition)
198 m_styleDefinition->GetStyle() = m_attributes;
199
200 return true;
201 }
202
203 /// Update the display
204 bool wxRichTextFormattingDialog::UpdateDisplay()
205 {
206 return TransferDataToWindow();
207 }
208
209 /// Apply the styles when a different tab is selected, so the previews are
210 /// up to date
211 void wxRichTextFormattingDialog::OnTabChanged(wxBookCtrlEvent& event)
212 {
213 if (GetBookCtrl() != event.GetEventObject())
214 {
215 event.Skip();
216 return;
217 }
218
219 int oldPageId = event.GetOldSelection();
220 if (oldPageId != -1)
221 {
222 wxWindow* page = GetBookCtrl()->GetPage(oldPageId);
223 if (page)
224 page->TransferDataFromWindow();
225 }
226
227 int pageId = event.GetSelection();
228 if (pageId != -1)
229 {
230 wxWindow* page = GetBookCtrl()->GetPage(pageId);
231 if (page)
232 page->TransferDataToWindow();
233 }
234 }
235
236 /// Respond to help command
237 void wxRichTextFormattingDialog::OnHelp(wxCommandEvent& event)
238 {
239 int selPage = GetBookCtrl()->GetSelection();
240 if (selPage != wxNOT_FOUND)
241 {
242 int pageId = -1;
243 if (selPage < (int) m_pageIds.GetCount())
244 pageId = m_pageIds[selPage];
245 if (!GetFormattingDialogFactory()->ShowHelp(pageId, this))
246 event.Skip();
247 }
248 }
249
250 void wxRichTextFormattingDialog::OnUpdateHelp(wxUpdateUIEvent& event)
251 {
252 event.Enable(true);
253 }
254
255 void wxRichTextFormattingDialog::SetFormattingDialogFactory(wxRichTextFormattingDialogFactory* factory)
256 {
257 if (ms_FormattingDialogFactory)
258 delete ms_FormattingDialogFactory;
259 ms_FormattingDialogFactory = factory;
260 }
261
262 // Find a page by class
263 wxWindow* wxRichTextFormattingDialog::FindPage(wxClassInfo* info) const
264 {
265 size_t i;
266 for (i = 0; i < GetBookCtrl()->GetPageCount(); i++)
267 {
268 wxWindow* w = GetBookCtrl()->GetPage(i);
269 if (w && w->GetClassInfo() == info)
270 return w;
271 }
272 return NULL;
273 }
274
275
276 /*!
277 * Factory for formatting dialog
278 */
279
280 /// Create all pages, under the dialog's book control, also calling AddPage
281 bool wxRichTextFormattingDialogFactory::CreatePages(long pages, wxRichTextFormattingDialog* dialog)
282 {
283 if (dialog->GetImageList())
284 dialog->GetBookCtrl()->SetImageList(dialog->GetImageList());
285
286 int availablePageCount = GetPageIdCount();
287 int i;
288 bool selected = false;
289 for (i = 0; i < availablePageCount; i ++)
290 {
291 int pageId = GetPageId(i);
292 if (pageId != -1 && (pages & pageId))
293 {
294 wxString title;
295 wxPanel* panel = CreatePage(pageId, title, dialog);
296 wxASSERT( panel != NULL );
297 if (panel)
298 {
299 int imageIndex = GetPageImage(pageId);
300 dialog->GetBookCtrl()->AddPage(panel, title, !selected, imageIndex);
301 selected = true;
302
303 dialog->AddPageId(pageId);
304 }
305 }
306 }
307
308 return true;
309 }
310
311 /// Create a page, given a page identifier
312 wxPanel* wxRichTextFormattingDialogFactory::CreatePage(int page, wxString& title, wxRichTextFormattingDialog* dialog)
313 {
314 if (page == wxRICHTEXT_FORMAT_STYLE_EDITOR)
315 {
316 wxRichTextStylePage* page = new wxRichTextStylePage(dialog->GetBookCtrl(), wxID_ANY);
317 title = _("Style");
318 return page;
319 }
320 else if (page == wxRICHTEXT_FORMAT_FONT)
321 {
322 wxRichTextFontPage* page = new wxRichTextFontPage(dialog->GetBookCtrl(), wxID_ANY);
323 title = _("Font");
324 return page;
325 }
326 else if (page == wxRICHTEXT_FORMAT_INDENTS_SPACING)
327 {
328 wxRichTextIndentsSpacingPage* page = new wxRichTextIndentsSpacingPage(dialog->GetBookCtrl(), wxID_ANY);
329 title = _("Indents && Spacing");
330 return page;
331 }
332 else if (page == wxRICHTEXT_FORMAT_TABS)
333 {
334 wxRichTextTabsPage* page = new wxRichTextTabsPage(dialog->GetBookCtrl(), wxID_ANY);
335 title = _("Tabs");
336 return page;
337 }
338 else if (page == wxRICHTEXT_FORMAT_BULLETS)
339 {
340 wxRichTextBulletsPage* page = new wxRichTextBulletsPage(dialog->GetBookCtrl(), wxID_ANY);
341 title = _("Bullets");
342 return page;
343 }
344 #ifndef __DMC__
345 else if (page == wxRICHTEXT_FORMAT_LIST_STYLE)
346 {
347 wxRichTextListStylePage* page = new wxRichTextListStylePage(dialog->GetBookCtrl(), wxID_ANY);
348 title = _("List Style");
349 return page;
350 }
351 #endif
352 else if (page == wxRICHTEXT_FORMAT_SIZE)
353 {
354 wxRichTextSizePage* page = new wxRichTextSizePage(dialog->GetBookCtrl(), wxID_ANY);
355 title = _("Size");
356 return page;
357 }
358 else if (page == wxRICHTEXT_FORMAT_MARGINS)
359 {
360 wxRichTextMarginsPage* page = new wxRichTextMarginsPage(dialog->GetBookCtrl(), wxID_ANY);
361 title = _("Margins");
362 return page;
363 }
364 else if (page == wxRICHTEXT_FORMAT_BORDERS)
365 {
366 wxRichTextBordersPage* page = new wxRichTextBordersPage(dialog->GetBookCtrl(), wxID_ANY);
367 title = _("Borders");
368 return page;
369 }
370 else if (page == wxRICHTEXT_FORMAT_BACKGROUND)
371 {
372 wxRichTextBackgroundPage* page = new wxRichTextBackgroundPage(dialog->GetBookCtrl(), wxID_ANY);
373 title = _("Background");
374 return page;
375 }
376 else
377 return NULL;
378 }
379
380 /// Enumerate all available page identifiers
381 int wxRichTextFormattingDialogFactory::GetPageId(int i) const
382 {
383 int pages[] = {
384 wxRICHTEXT_FORMAT_STYLE_EDITOR,
385 wxRICHTEXT_FORMAT_FONT,
386 wxRICHTEXT_FORMAT_INDENTS_SPACING,
387 wxRICHTEXT_FORMAT_BULLETS,
388 wxRICHTEXT_FORMAT_TABS,
389 wxRICHTEXT_FORMAT_LIST_STYLE,
390 wxRICHTEXT_FORMAT_SIZE,
391 wxRICHTEXT_FORMAT_MARGINS,
392 wxRICHTEXT_FORMAT_BORDERS,
393 wxRICHTEXT_FORMAT_BACKGROUND
394 };
395
396 if (i < 0 || i >= GetPageIdCount())
397 return -1;
398
399 return pages[i];
400 }
401
402 /// Get the number of available page identifiers
403 int wxRichTextFormattingDialogFactory::GetPageIdCount() const
404 {
405 #ifdef __DMC__
406 return 9;
407 #else
408 return 10;
409 #endif
410 }
411
412 /// Set the sheet style, called at the start of wxRichTextFormattingDialog::Create
413 bool wxRichTextFormattingDialogFactory::SetSheetStyle(wxRichTextFormattingDialog* dialog)
414 {
415 #if wxRICHTEXT_USE_TOOLBOOK
416 int sheetStyle = wxPROPSHEET_SHRINKTOFIT;
417 #ifdef __WXMAC__
418 sheetStyle |= wxPROPSHEET_BUTTONTOOLBOOK;
419 #else
420 sheetStyle |= wxPROPSHEET_TOOLBOOK;
421 #endif
422
423 dialog->SetSheetStyle(sheetStyle);
424 dialog->SetSheetInnerBorder(0);
425 dialog->SetSheetOuterBorder(0);
426 #else
427 wxUnusedVar(dialog);
428 #endif // wxRICHTEXT_USE_TOOLBOOK
429
430 return true;
431 }
432
433 /// Create the main dialog buttons
434 bool wxRichTextFormattingDialogFactory::CreateButtons(wxRichTextFormattingDialog* dialog)
435 {
436 int flags = wxOK|wxCANCEL;
437 #ifndef __WXWINCE__
438 if (dialog->GetWindowStyleFlag() & wxRICHTEXT_FORMAT_HELP_BUTTON)
439 flags |= wxHELP;
440 #endif
441
442 // If using a toolbook, also follow Mac style and don't create buttons
443 #if !wxRICHTEXT_USE_TOOLBOOK
444 dialog->CreateButtons(flags);
445 #endif
446
447 return true;
448 }
449
450 // Invoke help for the dialog
451 bool wxRichTextFormattingDialogFactory::ShowHelp(int WXUNUSED(page), wxRichTextFormattingDialog* dialog)
452 {
453 wxRichTextDialogPage* window = NULL;
454 int sel = dialog->GetBookCtrl()->GetSelection();
455 if (sel != -1)
456 window = wxDynamicCast(dialog->GetBookCtrl()->GetPage(sel), wxRichTextDialogPage);
457 if (window && window->GetHelpId() != -1)
458 {
459 if (window->GetUICustomization())
460 return window->GetUICustomization()->ShowHelp(dialog, window->GetHelpId());
461 else if (dialog->GetUICustomization())
462 return dialog->GetUICustomization()->ShowHelp(dialog, window->GetHelpId());
463 else
464 return false;
465 }
466 else if (dialog->GetHelpId() != -1 && dialog->GetUICustomization())
467 return dialog->ShowHelp(dialog);
468 else
469 return false;
470 }
471
472 /*
473 * Module to initialise and clean up handlers
474 */
475
476 class wxRichTextFormattingDialogModule: public wxModule
477 {
478 DECLARE_DYNAMIC_CLASS(wxRichTextFormattingDialogModule)
479 public:
480 wxRichTextFormattingDialogModule() {}
481 bool OnInit() { wxRichTextFormattingDialog::SetFormattingDialogFactory(new wxRichTextFormattingDialogFactory); return true; }
482 void OnExit() { wxRichTextFormattingDialog::SetFormattingDialogFactory(NULL); }
483 };
484
485 IMPLEMENT_DYNAMIC_CLASS(wxRichTextFormattingDialogModule, wxModule)
486
487 /*
488 * Font preview control
489 */
490
491 BEGIN_EVENT_TABLE(wxRichTextFontPreviewCtrl, wxWindow)
492 EVT_PAINT(wxRichTextFontPreviewCtrl::OnPaint)
493 END_EVENT_TABLE()
494
495 wxRichTextFontPreviewCtrl::wxRichTextFontPreviewCtrl(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& sz, long style)
496 {
497 if ((style & wxBORDER_MASK) == wxBORDER_DEFAULT)
498 style |= wxBORDER_THEME;
499
500 wxWindow::Create(parent, id, pos, sz, style);
501
502 SetBackgroundColour(*wxWHITE);
503 m_textEffects = 0;
504 }
505
506 void wxRichTextFontPreviewCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
507 {
508 wxPaintDC dc(this);
509
510 wxSize size = GetSize();
511 wxFont font = GetFont();
512
513 if ((GetTextEffects() & wxTEXT_ATTR_EFFECT_SUPERSCRIPT) || (GetTextEffects() & wxTEXT_ATTR_EFFECT_SUBSCRIPT))
514 {
515 double size = static_cast<double>(font.GetPointSize()) / wxSCRIPT_MUL_FACTOR;
516 font.SetPointSize( static_cast<int>(size) );
517 }
518
519 if ( font.Ok() )
520 {
521 dc.SetFont(font);
522 // Calculate vertical and horizontal centre
523 wxCoord w = 0, h = 0;
524
525 wxString text(_("ABCDEFGabcdefg12345"));
526 if (GetTextEffects() & wxTEXT_ATTR_EFFECT_CAPITALS)
527 text.MakeUpper();
528
529 dc.GetTextExtent( text, &w, &h);
530 int cx = wxMax(2, (size.x/2) - (w/2));
531 int cy = wxMax(2, (size.y/2) - (h/2));
532
533 if ( GetTextEffects() & wxTEXT_ATTR_EFFECT_SUPERSCRIPT )
534 cy -= h/2;
535 if ( GetTextEffects() & wxTEXT_ATTR_EFFECT_SUBSCRIPT )
536 cy += h/2;
537
538 dc.SetTextForeground(GetForegroundColour());
539 dc.SetClippingRegion(2, 2, size.x-4, size.y-4);
540 dc.DrawText(text, cx, cy);
541
542 if (GetTextEffects() & wxTEXT_ATTR_EFFECT_STRIKETHROUGH)
543 {
544 dc.SetPen(wxPen(GetForegroundColour(), 1));
545 dc.DrawLine(cx, (int) (cy + h/2 + 0.5), cx + w, (int) (cy + h/2 + 0.5));
546 }
547
548 dc.DestroyClippingRegion();
549 }
550 }
551
552 // Helper for pages to get the top-level dialog
553 wxRichTextFormattingDialog* wxRichTextFormattingDialog::GetDialog(wxWindow* win)
554 {
555 wxWindow* p = win->GetParent();
556 while (p && !p->IsKindOf(CLASSINFO(wxRichTextFormattingDialog)))
557 p = p->GetParent();
558 wxRichTextFormattingDialog* dialog = wxDynamicCast(p, wxRichTextFormattingDialog);
559 return dialog;
560 }
561
562 // Helper for pages to get the attributes
563 wxRichTextAttr* wxRichTextFormattingDialog::GetDialogAttributes(wxWindow* win)
564 {
565 wxRichTextFormattingDialog* dialog = GetDialog(win);
566 if (dialog)
567 return & dialog->GetAttributes();
568 else
569 return NULL;
570 }
571
572 #if 0
573 // Helper for pages to get the attributes to reset
574 wxRichTextAttr* wxRichTextFormattingDialog::GetDialogResetAttributes(wxWindow* win)
575 {
576 wxRichTextFormattingDialog* dialog = GetDialog(win);
577 if (dialog)
578 return & dialog->GetResetAttributes();
579 else
580 return NULL;
581 }
582 #endif
583
584 // Helper for pages to get the style
585 wxRichTextStyleDefinition* wxRichTextFormattingDialog::GetDialogStyleDefinition(wxWindow* win)
586 {
587 wxRichTextFormattingDialog* dialog = GetDialog(win);
588 if (dialog)
589 return dialog->GetStyleDefinition();
590 else
591 return NULL;
592 }
593
594 void wxRichTextFormattingDialog::SetDimensionValue(wxTextAttrDimension& dim, wxTextCtrl* valueCtrl, wxComboBox* unitsCtrl, wxCheckBox* checkBox)
595 {
596 int unitsIdx = 0;
597
598 if (!dim.IsValid())
599 {
600 checkBox->SetValue(false);
601 valueCtrl->SetValue(wxT("0"));
602 unitsCtrl->SetSelection(0);
603 #if 0
604 dim.SetValue(0);
605 dim.SetUnits(wxTEXT_ATTR_UNITS_PIXELS);
606 #endif
607 }
608 else
609 {
610 checkBox->SetValue(true);
611 if (dim.GetUnits() == wxTEXT_ATTR_UNITS_TENTHS_MM)
612 {
613 unitsIdx = 1;
614 float value = float(dim.GetValue()) / 100.0;
615 valueCtrl->SetValue(wxString::Format(wxT("%.2f"), value));
616 }
617 else if (dim.GetUnits() == wxTEXT_ATTR_UNITS_PERCENTAGE)
618 {
619 unitsIdx = 2;
620 valueCtrl->SetValue(wxString::Format(wxT("%d"), (int) dim.GetValue()));
621 }
622 else
623 {
624 unitsIdx = 0;
625 valueCtrl->SetValue(wxString::Format(wxT("%d"), (int) dim.GetValue()));
626 }
627
628 unitsCtrl->SetSelection(unitsIdx);
629 }
630 }
631
632 void wxRichTextFormattingDialog::GetDimensionValue(wxTextAttrDimension& dim, wxTextCtrl* valueCtrl, wxComboBox* unitsCtrl, wxCheckBox* checkBox)
633 {
634 if (!checkBox->GetValue())
635 {
636 dim.Reset();
637 }
638 else
639 {
640 if (unitsCtrl->GetSelection() == 1)
641 dim.SetUnits(wxTEXT_ATTR_UNITS_TENTHS_MM);
642 else if (unitsCtrl->GetSelection() == 2)
643 dim.SetUnits(wxTEXT_ATTR_UNITS_PERCENTAGE);
644 else
645 dim.SetUnits(wxTEXT_ATTR_UNITS_PIXELS);
646
647 int value = 0;
648 if (ConvertFromString(valueCtrl->GetValue(), value, dim.GetUnits()))
649 dim.SetValue(value);
650 }
651 }
652
653 bool wxRichTextFormattingDialog::ConvertFromString(const wxString& string, int& ret, int scale)
654 {
655 const wxChar* chars = string.GetData();
656 int remain = 2;
657 bool dot = false;
658 ret = 0;
659
660 for (unsigned int i = 0; i < string.Len() && remain; i++)
661 {
662 if (!(chars[i] >= wxT('0') && chars[i] <= wxT('9')) && !(scale == wxTEXT_ATTR_UNITS_TENTHS_MM && chars[i] == wxT('.')))
663 return false;
664
665 if (chars[i] == wxT('.'))
666 {
667 dot = true;
668 continue;
669 }
670
671 if (dot)
672 remain--;
673
674 ret = ret * 10 + chars[i] - wxT('0');
675 }
676
677 while (remain-- > 0 && scale == wxTEXT_ATTR_UNITS_TENTHS_MM)
678 ret *= 10;
679
680 return true;
681 }
682
683 /*
684 * A control for displaying a small preview of a colour or bitmap
685 */
686
687 BEGIN_EVENT_TABLE(wxRichTextColourSwatchCtrl, wxControl)
688 EVT_MOUSE_EVENTS(wxRichTextColourSwatchCtrl::OnMouseEvent)
689 END_EVENT_TABLE()
690
691 IMPLEMENT_CLASS(wxRichTextColourSwatchCtrl, wxControl)
692
693 wxRichTextColourSwatchCtrl::wxRichTextColourSwatchCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
694 {
695 if ((style & wxBORDER_MASK) == wxBORDER_DEFAULT)
696 style |= wxBORDER_THEME;
697
698 wxControl::Create(parent, id, pos, size, style);
699
700 SetColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
701 }
702
703 wxRichTextColourSwatchCtrl::~wxRichTextColourSwatchCtrl()
704 {
705 }
706
707 void wxRichTextColourSwatchCtrl::OnMouseEvent(wxMouseEvent& event)
708 {
709 if (event.LeftDown())
710 {
711 wxWindow* parent = GetParent();
712 while (parent != NULL && !parent->IsKindOf(CLASSINFO(wxDialog)) && !parent->IsKindOf(CLASSINFO(wxFrame)))
713 parent = parent->GetParent();
714
715 wxColourData data;
716 data.SetChooseFull(true);
717 data.SetColour(m_colour);
718 #if wxUSE_COLOURDLG
719 wxColourDialog *dialog = new wxColourDialog(parent, &data);
720 // Crashes on wxMac (no m_peer)
721 #ifndef __WXMAC__
722 dialog->SetTitle(_("Colour"));
723 #endif
724 if (dialog->ShowModal() == wxID_OK)
725 {
726 wxColourData retData = dialog->GetColourData();
727 m_colour = retData.GetColour();
728 SetBackgroundColour(m_colour);
729 }
730 dialog->Destroy();
731 #endif // wxUSE_COLOURDLG
732 Refresh();
733
734 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, GetId());
735 GetEventHandler()->ProcessEvent(event);
736 }
737 }
738
739 #if wxUSE_HTML
740
741 /*!
742 * wxRichTextFontListBox class declaration
743 * A listbox to display styles.
744 */
745
746 IMPLEMENT_CLASS(wxRichTextFontListBox, wxHtmlListBox)
747
748 BEGIN_EVENT_TABLE(wxRichTextFontListBox, wxHtmlListBox)
749 END_EVENT_TABLE()
750
751 wxRichTextFontListBox::wxRichTextFontListBox(wxWindow* parent, wxWindowID id, const wxPoint& pos,
752 const wxSize& size, long style)
753 {
754 Init();
755 Create(parent, id, pos, size, style);
756 }
757
758 bool wxRichTextFontListBox::Create(wxWindow* parent, wxWindowID id, const wxPoint& pos,
759 const wxSize& size, long style)
760 {
761 if ((style & wxBORDER_MASK) == wxBORDER_DEFAULT)
762 style |= wxBORDER_THEME;
763
764 return wxHtmlListBox::Create(parent, id, pos, size, style);
765 }
766
767 wxRichTextFontListBox::~wxRichTextFontListBox()
768 {
769 }
770
771 /// Returns the HTML for this item
772 wxString wxRichTextFontListBox::OnGetItem(size_t n) const
773 {
774 if (m_faceNames.GetCount() == 0)
775 return wxEmptyString;
776
777 wxString str = CreateHTML(m_faceNames[n]);
778 return str;
779 }
780
781 /// Get font name for index
782 wxString wxRichTextFontListBox::GetFaceName(size_t i) const
783 {
784 return m_faceNames[i];
785 }
786
787 /// Set selection for string, returning the index.
788 int wxRichTextFontListBox::SetFaceNameSelection(const wxString& name)
789 {
790 int i = m_faceNames.Index(name);
791 SetSelection(i);
792
793 return i;
794 }
795
796 /// Updates the font list
797 void wxRichTextFontListBox::UpdateFonts()
798 {
799 wxArrayString facenames = wxRichTextCtrl::GetAvailableFontNames();
800 m_faceNames = facenames;
801 m_faceNames.Sort();
802
803 SetItemCount(m_faceNames.GetCount());
804 Refresh();
805 }
806
807 #if 0
808 // Convert a colour to a 6-digit hex string
809 static wxString ColourToHexString(const wxColour& col)
810 {
811 wxString hex;
812
813 hex += wxDecToHex(col.Red());
814 hex += wxDecToHex(col.Green());
815 hex += wxDecToHex(col.Blue());
816
817 return hex;
818 }
819 #endif
820
821 /// Creates a suitable HTML fragment for a definition
822 wxString wxRichTextFontListBox::CreateHTML(const wxString& facename) const
823 {
824 wxString str = wxT("<font");
825
826 str << wxT(" size=\"+2\"");;
827
828 if (!facename.IsEmpty() && facename != _("(none)"))
829 str << wxT(" face=\"") << facename << wxT("\"");
830 /*
831 if (def->GetStyle().GetTextColour().Ok())
832 str << wxT(" color=\"#") << ColourToHexString(def->GetStyle().GetTextColour()) << wxT("\"");
833 */
834
835 str << wxT(">");
836
837 bool hasBold = false;
838
839 if (hasBold)
840 str << wxT("<b>");
841
842 str += facename;
843
844 if (hasBold)
845 str << wxT("</b>");
846
847 str << wxT("</font>");
848
849 return str;
850 }
851
852 #endif
853 // wxUSE_HTML
854
855
856 #endif
857 // wxUSE_RICHTEXT