]> git.saurik.com Git - wxWidgets.git/blame - src/richtext/richtextformatdlg.cpp
Make wxSpinCtrlGeneric usable as wxDVC editor control.
[wxWidgets.git] / src / richtext / richtextformatdlg.cpp
CommitLineData
97ff49b3
JS
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
62b51bfb 19#if wxUSE_RICHTEXT
97ff49b3 20
528e5cf8
PC
21#include "wx/richtext/richtextformatdlg.h"
22
97ff49b3
JS
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"
97ff49b3
JS
35 #include "wx/checkbox.h"
36 #include "wx/button.h"
37#endif // WX_PRECOMP
38
97ff49b3
JS
39#include "wx/bookctrl.h"
40#include "wx/colordlg.h"
97ff49b3
JS
41#include "wx/settings.h"
42#include "wx/module.h"
62b51bfb 43#include "wx/imaglist.h"
97ff49b3 44
97ff49b3
JS
45#include "wx/richtext/richtextctrl.h"
46#include "wx/richtext/richtextstyles.h"
47
ee5c8f01
SC
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"
dadd4f55 54#include "../../src/richtext/richtextliststylepage.cpp"
603f702b
JS
55#include "../../src/richtext/richtextsizepage.cpp"
56#include "../../src/richtext/richtextmarginspage.cpp"
57#include "../../src/richtext/richtextborderspage.cpp"
58#include "../../src/richtext/richtextbackgroundpage.cpp"
ee5c8f01 59#else
97ff49b3
JS
60#include "richtextfontpage.cpp"
61#include "richtextindentspage.cpp"
62#include "richtexttabspage.cpp"
63#include "richtextbulletspage.cpp"
603f702b
JS
64#include "richtextmarginspage.cpp"
65#include "richtextsizepage.cpp"
66#include "richtextborderspage.cpp"
67#include "richtextbackgroundpage.cpp"
1f71a770
JS
68// Digital Mars can't cope with this much code
69#ifndef __DMC__
70 #include "richtextliststylepage.cpp"
71#endif
97ff49b3 72#include "richtextstylepage.cpp"
ee5c8f01 73#endif
97ff49b3 74
61c006ec 75#if 0 // def __WXMAC__
c730fa07 76#define wxRICHTEXT_USE_TOOLBOOK 1
97ff49b3 77#else
c730fa07 78#define wxRICHTEXT_USE_TOOLBOOK 0
97ff49b3
JS
79#endif
80
dadd4f55
JS
81bool wxRichTextFormattingDialog::sm_showToolTips = false;
82
97ff49b3
JS
83IMPLEMENT_CLASS(wxRichTextFormattingDialog, wxPropertySheetDialog)
84
85BEGIN_EVENT_TABLE(wxRichTextFormattingDialog, wxPropertySheetDialog)
2b741a39 86 EVT_BOOKCTRL_PAGE_CHANGED(wxID_ANY, wxRichTextFormattingDialog::OnTabChanged)
603f702b
JS
87 EVT_BUTTON(wxID_HELP, wxRichTextFormattingDialog::OnHelp)
88 EVT_UPDATE_UI(wxID_HELP, wxRichTextFormattingDialog::OnUpdateHelp)
97ff49b3
JS
89END_EVENT_TABLE()
90
603f702b
JS
91IMPLEMENT_HELP_PROVISION(wxRichTextFormattingDialog)
92
97ff49b3
JS
93wxRichTextFormattingDialogFactory* wxRichTextFormattingDialog::ms_FormattingDialogFactory = NULL;
94
95void wxRichTextFormattingDialog::Init()
96{
97 m_imageList = NULL;
98 m_styleDefinition = NULL;
99 m_styleSheet = NULL;
603f702b 100 m_object = NULL;
97ff49b3
JS
101}
102
103wxRichTextFormattingDialog::~wxRichTextFormattingDialog()
104{
105 delete m_imageList;
106 delete m_styleDefinition;
107}
108
109bool 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,
528e5cf8 119 style | (int)wxPlatform::IfNot(wxOS_WINDOWS_CE, resizeBorder)
97ff49b3
JS
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
131bool wxRichTextFormattingDialog::GetStyle(wxRichTextCtrl* ctrl, const wxRichTextRange& range)
132{
603f702b 133 if (ctrl->GetFocusObject()->GetStyleForRange(range.ToInternal(), m_attributes))
97ff49b3
JS
134 return UpdateDisplay();
135 else
136 return false;
137}
138
139/// Apply attributes to the given range, only applying if necessary (wxRICHTEXT_SETSTYLE_OPTIMIZE)
140bool wxRichTextFormattingDialog::ApplyStyle(wxRichTextCtrl* ctrl, const wxRichTextRange& range, int flags)
141{
142 return ctrl->SetStyleEx(range, m_attributes, flags);
143}
144
603f702b
JS
145// Apply attributes to the object being edited, if any
146bool 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
97ff49b3 159/// Set the attributes and optionally update the display
24777478 160bool wxRichTextFormattingDialog::SetStyle(const wxRichTextAttr& style, bool update)
97ff49b3
JS
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
169bool 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
181bool 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
192bool 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
204bool 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
2b741a39 211void wxRichTextFormattingDialog::OnTabChanged(wxBookCtrlEvent& event)
97ff49b3
JS
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
1807a1f3
JS
236/// Respond to help command
237void wxRichTextFormattingDialog::OnHelp(wxCommandEvent& event)
238{
239 int selPage = GetBookCtrl()->GetSelection();
240 if (selPage != wxNOT_FOUND)
241 {
603f702b
JS
242 int pageId = -1;
243 if (selPage < (int) m_pageIds.GetCount())
244 pageId = m_pageIds[selPage];
1807a1f3
JS
245 if (!GetFormattingDialogFactory()->ShowHelp(pageId, this))
246 event.Skip();
247 }
248}
249
603f702b
JS
250void wxRichTextFormattingDialog::OnUpdateHelp(wxUpdateUIEvent& event)
251{
252 event.Enable(true);
253}
254
97ff49b3
JS
255void wxRichTextFormattingDialog::SetFormattingDialogFactory(wxRichTextFormattingDialogFactory* factory)
256{
257 if (ms_FormattingDialogFactory)
258 delete ms_FormattingDialogFactory;
259 ms_FormattingDialogFactory = factory;
260}
261
603f702b
JS
262// Find a page by class
263wxWindow* 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
97ff49b3
JS
276/*!
277 * Factory for formatting dialog
278 */
279
280/// Create all pages, under the dialog's book control, also calling AddPage
281bool 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;
61c006ec 288 bool selected = false;
97ff49b3
JS
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);
61c006ec
JS
300 dialog->GetBookCtrl()->AddPage(panel, title, !selected, imageIndex);
301 selected = true;
41a85215 302
1807a1f3 303 dialog->AddPageId(pageId);
97ff49b3
JS
304 }
305 }
306 }
2b741a39 307
97ff49b3
JS
308 return true;
309}
310
311/// Create a page, given a page identifier
312wxPanel* 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 }
1f71a770 344#ifndef __DMC__
dadd4f55
JS
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 }
1f71a770 351#endif
603f702b
JS
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 }
97ff49b3
JS
376 else
377 return NULL;
378}
379
380/// Enumerate all available page identifiers
381int 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,
dadd4f55 388 wxRICHTEXT_FORMAT_TABS,
603f702b
JS
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())
97ff49b3
JS
397 return -1;
398
399 return pages[i];
400}
401
402/// Get the number of available page identifiers
403int wxRichTextFormattingDialogFactory::GetPageIdCount() const
404{
1f71a770 405#ifdef __DMC__
603f702b 406 return 9;
1f71a770 407#else
603f702b 408 return 10;
1f71a770 409#endif
97ff49b3
JS
410}
411
412/// Set the sheet style, called at the start of wxRichTextFormattingDialog::Create
413bool wxRichTextFormattingDialogFactory::SetSheetStyle(wxRichTextFormattingDialog* dialog)
414{
d0cf4953
VZ
415#if wxRICHTEXT_USE_TOOLBOOK
416 int sheetStyle = wxPROPSHEET_SHRINKTOFIT;
97ff49b3 417#ifdef __WXMAC__
d0cf4953 418 sheetStyle |= wxPROPSHEET_BUTTONTOOLBOOK;
97ff49b3 419#else
d0cf4953 420 sheetStyle |= wxPROPSHEET_TOOLBOOK;
97ff49b3
JS
421#endif
422
d0cf4953
VZ
423 dialog->SetSheetStyle(sheetStyle);
424 dialog->SetSheetInnerBorder(0);
425 dialog->SetSheetOuterBorder(0);
c730fa07 426#else
44cc96a8 427 wxUnusedVar(dialog);
d0cf4953 428#endif // wxRICHTEXT_USE_TOOLBOOK
97ff49b3
JS
429
430 return true;
431}
432
433/// Create the main dialog buttons
434bool wxRichTextFormattingDialogFactory::CreateButtons(wxRichTextFormattingDialog* dialog)
435{
97ff49b3
JS
436 int flags = wxOK|wxCANCEL;
437#ifndef __WXWINCE__
dadd4f55
JS
438 if (dialog->GetWindowStyleFlag() & wxRICHTEXT_FORMAT_HELP_BUTTON)
439 flags |= wxHELP;
97ff49b3
JS
440#endif
441
d0cf4953
VZ
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
97ff49b3
JS
446
447 return true;
448}
449
603f702b
JS
450// Invoke help for the dialog
451bool 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
97ff49b3
JS
472/*
473 * Module to initialise and clean up handlers
474 */
475
476class wxRichTextFormattingDialogModule: public wxModule
477{
478DECLARE_DYNAMIC_CLASS(wxRichTextFormattingDialogModule)
479public:
480 wxRichTextFormattingDialogModule() {}
47b378bd
VS
481 bool OnInit() { wxRichTextFormattingDialog::SetFormattingDialogFactory(new wxRichTextFormattingDialogFactory); return true; }
482 void OnExit() { wxRichTextFormattingDialog::SetFormattingDialogFactory(NULL); }
97ff49b3
JS
483};
484
485IMPLEMENT_DYNAMIC_CLASS(wxRichTextFormattingDialogModule, wxModule)
486
487/*
488 * Font preview control
489 */
490
491BEGIN_EVENT_TABLE(wxRichTextFontPreviewCtrl, wxWindow)
492 EVT_PAINT(wxRichTextFontPreviewCtrl::OnPaint)
493END_EVENT_TABLE()
494
2fce6547
JS
495wxRichTextFontPreviewCtrl::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
97ff49b3
JS
506void wxRichTextFontPreviewCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
507{
508 wxPaintDC dc(this);
509
510 wxSize size = GetSize();
511 wxFont font = GetFont();
512
30bf7630
JS
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
97ff49b3
JS
519 if ( font.Ok() )
520 {
521 dc.SetFont(font);
522 // Calculate vertical and horizontal centre
0bc58f95 523 wxCoord w = 0, h = 0;
97ff49b3
JS
524
525 wxString text(_("ABCDEFGabcdefg12345"));
42688aea
JS
526 if (GetTextEffects() & wxTEXT_ATTR_EFFECT_CAPITALS)
527 text.MakeUpper();
97ff49b3
JS
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
30bf7630
JS
533 if ( GetTextEffects() & wxTEXT_ATTR_EFFECT_SUPERSCRIPT )
534 cy -= h/2;
535 if ( GetTextEffects() & wxTEXT_ATTR_EFFECT_SUBSCRIPT )
536 cy += h/2;
537
97ff49b3
JS
538 dc.SetTextForeground(GetForegroundColour());
539 dc.SetClippingRegion(2, 2, size.x-4, size.y-4);
540 dc.DrawText(text, cx, cy);
c730fa07 541
42688aea
JS
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 }
c730fa07 547
97ff49b3
JS
548 dc.DestroyClippingRegion();
549 }
550}
551
552// Helper for pages to get the top-level dialog
553wxRichTextFormattingDialog* 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
97ff49b3 562// Helper for pages to get the attributes
24777478 563wxRichTextAttr* wxRichTextFormattingDialog::GetDialogAttributes(wxWindow* win)
97ff49b3
JS
564{
565 wxRichTextFormattingDialog* dialog = GetDialog(win);
566 if (dialog)
567 return & dialog->GetAttributes();
568 else
569 return NULL;
570}
571
603f702b
JS
572#if 0
573// Helper for pages to get the attributes to reset
574wxRichTextAttr* 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
97ff49b3
JS
584// Helper for pages to get the style
585wxRichTextStyleDefinition* wxRichTextFormattingDialog::GetDialogStyleDefinition(wxWindow* win)
586{
587 wxRichTextFormattingDialog* dialog = GetDialog(win);
588 if (dialog)
589 return dialog->GetStyleDefinition();
590 else
591 return NULL;
592}
593
603f702b
JS
594void wxRichTextFormattingDialog::SetDimensionValue(wxTextAttrDimension& dim, wxTextCtrl* valueCtrl, wxComboBox* unitsCtrl, wxCheckBox* checkBox)
595{
596 int unitsIdx = 0;
706465df 597
603f702b
JS
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;
706465df 614 float value = float(dim.GetValue()) / 100.0;
603f702b
JS
615 valueCtrl->SetValue(wxString::Format(wxT("%.2f"), value));
616 }
706465df
JS
617 else if (dim.GetUnits() == wxTEXT_ATTR_UNITS_PERCENTAGE)
618 {
619 unitsIdx = 2;
620 valueCtrl->SetValue(wxString::Format(wxT("%d"), (int) dim.GetValue()));
621 }
603f702b
JS
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
632void 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);
706465df
JS
642 else if (unitsCtrl->GetSelection() == 2)
643 dim.SetUnits(wxTEXT_ATTR_UNITS_PERCENTAGE);
603f702b
JS
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
653bool 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
97ff49b3
JS
683/*
684 * A control for displaying a small preview of a colour or bitmap
685 */
686
687BEGIN_EVENT_TABLE(wxRichTextColourSwatchCtrl, wxControl)
688 EVT_MOUSE_EVENTS(wxRichTextColourSwatchCtrl::OnMouseEvent)
689END_EVENT_TABLE()
690
691IMPLEMENT_CLASS(wxRichTextColourSwatchCtrl, wxControl)
692
2fce6547 693wxRichTextColourSwatchCtrl::wxRichTextColourSwatchCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
97ff49b3 694{
2fce6547
JS
695 if ((style & wxBORDER_MASK) == wxBORDER_DEFAULT)
696 style |= wxBORDER_THEME;
697
698 wxControl::Create(parent, id, pos, size, style);
699
97ff49b3 700 SetColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
97ff49b3
JS
701}
702
703wxRichTextColourSwatchCtrl::~wxRichTextColourSwatchCtrl()
704{
705}
706
707void 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);
2b741a39 718#if wxUSE_COLOURDLG
97ff49b3
JS
719 wxColourDialog *dialog = new wxColourDialog(parent, &data);
720 // Crashes on wxMac (no m_peer)
721#ifndef __WXMAC__
2fce6547 722 dialog->SetTitle(_("Colour"));
97ff49b3
JS
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();
2b741a39 731#endif // wxUSE_COLOURDLG
97ff49b3
JS
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
746IMPLEMENT_CLASS(wxRichTextFontListBox, wxHtmlListBox)
747
748BEGIN_EVENT_TABLE(wxRichTextFontListBox, wxHtmlListBox)
749END_EVENT_TABLE()
750
751wxRichTextFontListBox::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
758bool wxRichTextFontListBox::Create(wxWindow* parent, wxWindowID id, const wxPoint& pos,
759 const wxSize& size, long style)
760{
2fce6547
JS
761 if ((style & wxBORDER_MASK) == wxBORDER_DEFAULT)
762 style |= wxBORDER_THEME;
763
97ff49b3
JS
764 return wxHtmlListBox::Create(parent, id, pos, size, style);
765}
766
767wxRichTextFontListBox::~wxRichTextFontListBox()
768{
769}
770
771/// Returns the HTML for this item
772wxString 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
782wxString wxRichTextFontListBox::GetFaceName(size_t i) const
783{
784 return m_faceNames[i];
785}
786
787/// Set selection for string, returning the index.
788int 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
797void wxRichTextFontListBox::UpdateFonts()
798{
dadd4f55 799 wxArrayString facenames = wxRichTextCtrl::GetAvailableFontNames();
97ff49b3
JS
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
809static 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
822wxString 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