1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/richtext/richtextformatdlg.cpp
3 // Purpose: Formatting dialog for wxRichTextCtrl
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
21 #include "wx/richtext/richtextformatdlg.h"
24 #include "wx/listbox.h"
25 #include "wx/combobox.h"
26 #include "wx/textctrl.h"
28 #include "wx/stattext.h"
29 #include "wx/statline.h"
30 #include "wx/radiobut.h"
32 #include "wx/bitmap.h"
33 #include "wx/dcclient.h"
35 #include "wx/checkbox.h"
36 #include "wx/button.h"
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"
45 #include "wx/richtext/richtextctrl.h"
46 #include "wx/richtext/richtextstyles.h"
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"
56 #include "richtextfontpage.cpp"
57 #include "richtextindentspage.cpp"
58 #include "richtexttabspage.cpp"
59 #include "richtextbulletspage.cpp"
60 #include "richtextstylepage.cpp"
61 #include "richtextliststylepage.cpp"
64 #if 0 // def __WXMAC__
65 #define wxRICHTEXT_USE_TOOLBOOK true
67 #define wxRICHTEXT_USE_TOOLBOOK false
70 bool wxRichTextFormattingDialog::sm_showToolTips
= false;
72 IMPLEMENT_CLASS(wxRichTextFormattingDialog
, wxPropertySheetDialog
)
74 BEGIN_EVENT_TABLE(wxRichTextFormattingDialog
, wxPropertySheetDialog
)
75 EVT_BOOKCTRL_PAGE_CHANGED(wxID_ANY
, wxRichTextFormattingDialog::OnTabChanged
)
78 wxRichTextFormattingDialogFactory
* wxRichTextFormattingDialog::ms_FormattingDialogFactory
= NULL
;
80 void wxRichTextFormattingDialog::Init()
83 m_styleDefinition
= NULL
;
87 wxRichTextFormattingDialog::~wxRichTextFormattingDialog()
90 delete m_styleDefinition
;
93 bool wxRichTextFormattingDialog::Create(long flags
, wxWindow
* parent
, const wxString
& title
, wxWindowID id
,
94 const wxPoint
& pos
, const wxSize
& sz
, long style
)
96 SetExtraStyle(wxDIALOG_EX_CONTEXTHELP
|wxWS_EX_VALIDATE_RECURSIVELY
);
98 int resizeBorder
= wxRESIZE_BORDER
;
100 GetFormattingDialogFactory()->SetSheetStyle(this);
102 wxPropertySheetDialog::Create(parent
, id
, title
, pos
, sz
,
103 style
| (int)wxPlatform::IfNot(wxOS_WINDOWS_CE
, resizeBorder
)
106 GetFormattingDialogFactory()->CreateButtons(this);
107 GetFormattingDialogFactory()->CreatePages(flags
, this);
114 /// Get attributes from the given range
115 bool wxRichTextFormattingDialog::GetStyle(wxRichTextCtrl
* ctrl
, const wxRichTextRange
& range
)
117 if (ctrl
->GetBuffer().GetStyleForRange(range
.ToInternal(), m_attributes
))
118 return UpdateDisplay();
123 /// Apply attributes to the given range, only applying if necessary (wxRICHTEXT_SETSTYLE_OPTIMIZE)
124 bool wxRichTextFormattingDialog::ApplyStyle(wxRichTextCtrl
* ctrl
, const wxRichTextRange
& range
, int flags
)
126 return ctrl
->SetStyleEx(range
, m_attributes
, flags
);
129 /// Set the attributes and optionally update the display
130 bool wxRichTextFormattingDialog::SetStyle(const wxTextAttrEx
& style
, bool update
)
132 m_attributes
= style
;
138 /// Set the style definition and optionally update the display
139 bool wxRichTextFormattingDialog::SetStyleDefinition(const wxRichTextStyleDefinition
& styleDef
, wxRichTextStyleSheet
* sheet
, bool update
)
141 m_styleSheet
= sheet
;
143 if (m_styleDefinition
)
144 delete m_styleDefinition
;
145 m_styleDefinition
= styleDef
.Clone();
147 return SetStyle(m_styleDefinition
->GetStyle(), update
);
150 /// Transfers the data and from to the window
151 bool wxRichTextFormattingDialog::TransferDataToWindow()
153 if (m_styleDefinition
)
154 m_attributes
= m_styleDefinition
->GetStyle();
156 if (!wxPropertySheetDialog::TransferDataToWindow())
162 bool wxRichTextFormattingDialog::TransferDataFromWindow()
164 if (!wxPropertySheetDialog::TransferDataFromWindow())
167 if (m_styleDefinition
)
168 m_styleDefinition
->GetStyle() = m_attributes
;
173 /// Update the display
174 bool wxRichTextFormattingDialog::UpdateDisplay()
176 return TransferDataToWindow();
179 /// Apply the styles when a different tab is selected, so the previews are
181 void wxRichTextFormattingDialog::OnTabChanged(wxBookCtrlEvent
& event
)
183 if (GetBookCtrl() != event
.GetEventObject())
189 int oldPageId
= event
.GetOldSelection();
192 wxWindow
* page
= GetBookCtrl()->GetPage(oldPageId
);
194 page
->TransferDataFromWindow();
197 int pageId
= event
.GetSelection();
200 wxWindow
* page
= GetBookCtrl()->GetPage(pageId
);
202 page
->TransferDataToWindow();
206 /// Respond to help command
207 void wxRichTextFormattingDialog::OnHelp(wxCommandEvent
& event
)
209 int selPage
= GetBookCtrl()->GetSelection();
210 if (selPage
!= wxNOT_FOUND
)
212 int pageId
= m_pageIds
[selPage
];
213 if (!GetFormattingDialogFactory()->ShowHelp(pageId
, this))
218 void wxRichTextFormattingDialog::SetFormattingDialogFactory(wxRichTextFormattingDialogFactory
* factory
)
220 if (ms_FormattingDialogFactory
)
221 delete ms_FormattingDialogFactory
;
222 ms_FormattingDialogFactory
= factory
;
226 * Factory for formatting dialog
229 /// Create all pages, under the dialog's book control, also calling AddPage
230 bool wxRichTextFormattingDialogFactory::CreatePages(long pages
, wxRichTextFormattingDialog
* dialog
)
232 if (dialog
->GetImageList())
233 dialog
->GetBookCtrl()->SetImageList(dialog
->GetImageList());
235 int availablePageCount
= GetPageIdCount();
237 bool selected
= false;
238 for (i
= 0; i
< availablePageCount
; i
++)
240 int pageId
= GetPageId(i
);
241 if (pageId
!= -1 && (pages
& pageId
))
244 wxPanel
* panel
= CreatePage(pageId
, title
, dialog
);
245 wxASSERT( panel
!= NULL
);
248 int imageIndex
= GetPageImage(pageId
);
249 dialog
->GetBookCtrl()->AddPage(panel
, title
, !selected
, imageIndex
);
252 dialog
->AddPageId(pageId
);
260 /// Create a page, given a page identifier
261 wxPanel
* wxRichTextFormattingDialogFactory::CreatePage(int page
, wxString
& title
, wxRichTextFormattingDialog
* dialog
)
263 if (page
== wxRICHTEXT_FORMAT_STYLE_EDITOR
)
265 wxRichTextStylePage
* page
= new wxRichTextStylePage(dialog
->GetBookCtrl(), wxID_ANY
);
269 else if (page
== wxRICHTEXT_FORMAT_FONT
)
271 wxRichTextFontPage
* page
= new wxRichTextFontPage(dialog
->GetBookCtrl(), wxID_ANY
);
275 else if (page
== wxRICHTEXT_FORMAT_INDENTS_SPACING
)
277 wxRichTextIndentsSpacingPage
* page
= new wxRichTextIndentsSpacingPage(dialog
->GetBookCtrl(), wxID_ANY
);
278 title
= _("Indents && Spacing");
281 else if (page
== wxRICHTEXT_FORMAT_TABS
)
283 wxRichTextTabsPage
* page
= new wxRichTextTabsPage(dialog
->GetBookCtrl(), wxID_ANY
);
287 else if (page
== wxRICHTEXT_FORMAT_BULLETS
)
289 wxRichTextBulletsPage
* page
= new wxRichTextBulletsPage(dialog
->GetBookCtrl(), wxID_ANY
);
290 title
= _("Bullets");
293 else if (page
== wxRICHTEXT_FORMAT_LIST_STYLE
)
295 wxRichTextListStylePage
* page
= new wxRichTextListStylePage(dialog
->GetBookCtrl(), wxID_ANY
);
296 title
= _("List Style");
303 /// Enumerate all available page identifiers
304 int wxRichTextFormattingDialogFactory::GetPageId(int i
) const
307 wxRICHTEXT_FORMAT_STYLE_EDITOR
,
308 wxRICHTEXT_FORMAT_FONT
,
309 wxRICHTEXT_FORMAT_INDENTS_SPACING
,
310 wxRICHTEXT_FORMAT_BULLETS
,
311 wxRICHTEXT_FORMAT_TABS
,
312 wxRICHTEXT_FORMAT_LIST_STYLE
};
320 /// Get the number of available page identifiers
321 int wxRichTextFormattingDialogFactory::GetPageIdCount() const
326 /// Set the sheet style, called at the start of wxRichTextFormattingDialog::Create
327 bool wxRichTextFormattingDialogFactory::SetSheetStyle(wxRichTextFormattingDialog
* dialog
)
329 bool useToolBook
= wxRICHTEXT_USE_TOOLBOOK
;
332 int sheetStyle
= wxPROPSHEET_SHRINKTOFIT
;
334 sheetStyle
|= wxPROPSHEET_BUTTONTOOLBOOK
;
336 sheetStyle
|= wxPROPSHEET_TOOLBOOK
;
339 dialog
->SetSheetStyle(sheetStyle
);
340 dialog
->SetSheetInnerBorder(0);
341 dialog
->SetSheetOuterBorder(0);
347 /// Create the main dialog buttons
348 bool wxRichTextFormattingDialogFactory::CreateButtons(wxRichTextFormattingDialog
* dialog
)
350 bool useToolBook
= wxRICHTEXT_USE_TOOLBOOK
;
352 // If using a toolbook, also follow Mac style and don't create buttons
353 int flags
= wxOK
|wxCANCEL
;
355 if (dialog
->GetWindowStyleFlag() & wxRICHTEXT_FORMAT_HELP_BUTTON
)
360 dialog
->CreateButtons(flags
);
366 * Module to initialise and clean up handlers
369 class wxRichTextFormattingDialogModule
: public wxModule
371 DECLARE_DYNAMIC_CLASS(wxRichTextFormattingDialogModule
)
373 wxRichTextFormattingDialogModule() {}
374 bool OnInit() { wxRichTextFormattingDialog::SetFormattingDialogFactory(new wxRichTextFormattingDialogFactory
); return true; };
375 void OnExit() { wxRichTextFormattingDialog::SetFormattingDialogFactory(NULL
); };
378 IMPLEMENT_DYNAMIC_CLASS(wxRichTextFormattingDialogModule
, wxModule
)
381 * Font preview control
384 BEGIN_EVENT_TABLE(wxRichTextFontPreviewCtrl
, wxWindow
)
385 EVT_PAINT(wxRichTextFontPreviewCtrl::OnPaint
)
388 void wxRichTextFontPreviewCtrl::OnPaint(wxPaintEvent
& WXUNUSED(event
))
392 wxSize size
= GetSize();
393 wxFont font
= GetFont();
398 // Calculate vertical and horizontal centre
401 wxString
text(_("ABCDEFGabcdefg12345"));
403 dc
.GetTextExtent( text
, &w
, &h
);
404 int cx
= wxMax(2, (size
.x
/2) - (w
/2));
405 int cy
= wxMax(2, (size
.y
/2) - (h
/2));
407 dc
.SetTextForeground(GetForegroundColour());
408 dc
.SetClippingRegion(2, 2, size
.x
-4, size
.y
-4);
409 dc
.DrawText(text
, cx
, cy
);
410 dc
.DestroyClippingRegion();
414 // Helper for pages to get the top-level dialog
415 wxRichTextFormattingDialog
* wxRichTextFormattingDialog::GetDialog(wxWindow
* win
)
417 wxWindow
* p
= win
->GetParent();
418 while (p
&& !p
->IsKindOf(CLASSINFO(wxRichTextFormattingDialog
)))
420 wxRichTextFormattingDialog
* dialog
= wxDynamicCast(p
, wxRichTextFormattingDialog
);
425 // Helper for pages to get the attributes
426 wxTextAttrEx
* wxRichTextFormattingDialog::GetDialogAttributes(wxWindow
* win
)
428 wxRichTextFormattingDialog
* dialog
= GetDialog(win
);
430 return & dialog
->GetAttributes();
435 // Helper for pages to get the style
436 wxRichTextStyleDefinition
* wxRichTextFormattingDialog::GetDialogStyleDefinition(wxWindow
* win
)
438 wxRichTextFormattingDialog
* dialog
= GetDialog(win
);
440 return dialog
->GetStyleDefinition();
446 * A control for displaying a small preview of a colour or bitmap
449 BEGIN_EVENT_TABLE(wxRichTextColourSwatchCtrl
, wxControl
)
450 EVT_MOUSE_EVENTS(wxRichTextColourSwatchCtrl::OnMouseEvent
)
453 IMPLEMENT_CLASS(wxRichTextColourSwatchCtrl
, wxControl
)
455 wxRichTextColourSwatchCtrl::wxRichTextColourSwatchCtrl(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
, const wxSize
& size
, long style
):
456 wxControl(parent
, id
, pos
, size
, style
)
458 SetColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
));
459 SetBackgroundStyle(wxBG_STYLE_COLOUR
);
462 wxRichTextColourSwatchCtrl::~wxRichTextColourSwatchCtrl()
466 void wxRichTextColourSwatchCtrl::OnMouseEvent(wxMouseEvent
& event
)
468 if (event
.LeftDown())
470 wxWindow
* parent
= GetParent();
471 while (parent
!= NULL
&& !parent
->IsKindOf(CLASSINFO(wxDialog
)) && !parent
->IsKindOf(CLASSINFO(wxFrame
)))
472 parent
= parent
->GetParent();
475 data
.SetChooseFull(true);
476 data
.SetColour(m_colour
);
478 wxColourDialog
*dialog
= new wxColourDialog(parent
, &data
);
479 // Crashes on wxMac (no m_peer)
481 dialog
->SetTitle(_("Background colour"));
483 if (dialog
->ShowModal() == wxID_OK
)
485 wxColourData retData
= dialog
->GetColourData();
486 m_colour
= retData
.GetColour();
487 SetBackgroundColour(m_colour
);
490 #endif // wxUSE_COLOURDLG
493 wxCommandEvent
event(wxEVT_COMMAND_BUTTON_CLICKED
, GetId());
494 GetEventHandler()->ProcessEvent(event
);
501 * wxRichTextFontListBox class declaration
502 * A listbox to display styles.
505 IMPLEMENT_CLASS(wxRichTextFontListBox
, wxHtmlListBox
)
507 BEGIN_EVENT_TABLE(wxRichTextFontListBox
, wxHtmlListBox
)
510 wxRichTextFontListBox::wxRichTextFontListBox(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
511 const wxSize
& size
, long style
)
514 Create(parent
, id
, pos
, size
, style
);
517 bool wxRichTextFontListBox::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
518 const wxSize
& size
, long style
)
520 return wxHtmlListBox::Create(parent
, id
, pos
, size
, style
);
523 wxRichTextFontListBox::~wxRichTextFontListBox()
527 /// Returns the HTML for this item
528 wxString
wxRichTextFontListBox::OnGetItem(size_t n
) const
530 if (m_faceNames
.GetCount() == 0)
531 return wxEmptyString
;
533 wxString str
= CreateHTML(m_faceNames
[n
]);
537 /// Get font name for index
538 wxString
wxRichTextFontListBox::GetFaceName(size_t i
) const
540 return m_faceNames
[i
];
543 /// Set selection for string, returning the index.
544 int wxRichTextFontListBox::SetFaceNameSelection(const wxString
& name
)
546 int i
= m_faceNames
.Index(name
);
552 /// Updates the font list
553 void wxRichTextFontListBox::UpdateFonts()
555 wxArrayString facenames
= wxRichTextCtrl::GetAvailableFontNames();
556 m_faceNames
= facenames
;
559 SetItemCount(m_faceNames
.GetCount());
564 // Convert a colour to a 6-digit hex string
565 static wxString
ColourToHexString(const wxColour
& col
)
569 hex
+= wxDecToHex(col
.Red());
570 hex
+= wxDecToHex(col
.Green());
571 hex
+= wxDecToHex(col
.Blue());
577 /// Creates a suitable HTML fragment for a definition
578 wxString
wxRichTextFontListBox::CreateHTML(const wxString
& facename
) const
580 wxString str
= wxT("<font");
582 str
<< wxT(" size=\"+2\"");;
584 if (!facename
.IsEmpty() && facename
!= _("(none)"))
585 str
<< wxT(" face=\"") << facename
<< wxT("\"");
587 if (def->GetStyle().GetTextColour().Ok())
588 str << wxT(" color=\"#") << ColourToHexString(def->GetStyle().GetTextColour()) << wxT("\"");
593 bool hasBold
= false;
603 str
<< wxT("</font>");