1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/richtext/richtextstyles.cpp
3 // Purpose: Style management 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/richtextstyles.h"
27 #include "wx/filename.h"
28 #include "wx/clipbrd.h"
29 #include "wx/wfstream.h"
30 #include "wx/settings.h"
32 #include "wx/richtext/richtextctrl.h"
34 IMPLEMENT_CLASS(wxRichTextStyleDefinition
, wxObject
)
35 IMPLEMENT_CLASS(wxRichTextCharacterStyleDefinition
, wxRichTextStyleDefinition
)
36 IMPLEMENT_CLASS(wxRichTextParagraphStyleDefinition
, wxRichTextStyleDefinition
)
37 IMPLEMENT_CLASS(wxRichTextListStyleDefinition
, wxRichTextParagraphStyleDefinition
)
43 void wxRichTextStyleDefinition::Copy(const wxRichTextStyleDefinition
& def
)
46 m_baseStyle
= def
.m_baseStyle
;
47 m_style
= def
.m_style
;
48 m_description
= def
.m_description
;
51 bool wxRichTextStyleDefinition::Eq(const wxRichTextStyleDefinition
& def
) const
53 return (m_name
== def
.m_name
&& m_baseStyle
== def
.m_baseStyle
&& m_style
== def
.m_style
);
56 /// Gets the style combined with the base style
57 wxTextAttr
wxRichTextStyleDefinition::GetStyleMergedWithBase(const wxRichTextStyleSheet
* sheet
) const
59 if (!m_baseStyle
.IsEmpty())
61 wxRichTextStyleDefinition
* baseStyle
= sheet
->FindStyle(m_baseStyle
);
64 wxTextAttr baseAttr
= baseStyle
->GetStyleMergedWithBase(sheet
);
65 baseAttr
.Apply(m_style
, NULL
);
73 * Paragraph style definition
76 void wxRichTextParagraphStyleDefinition::Copy(const wxRichTextParagraphStyleDefinition
& def
)
78 wxRichTextStyleDefinition::Copy(def
);
80 m_nextStyle
= def
.m_nextStyle
;
83 bool wxRichTextParagraphStyleDefinition::operator ==(const wxRichTextParagraphStyleDefinition
& def
) const
85 return (Eq(def
) && m_nextStyle
== def
.m_nextStyle
);
89 * List style definition
92 void wxRichTextListStyleDefinition::Copy(const wxRichTextListStyleDefinition
& def
)
94 wxRichTextParagraphStyleDefinition::Copy(def
);
97 for (i
= 0; i
< 10; i
++)
98 m_levelStyles
[i
] = def
.m_levelStyles
[i
];
101 bool wxRichTextListStyleDefinition::operator ==(const wxRichTextListStyleDefinition
& def
) const
106 for (i
= 0; i
< 10; i
++)
107 if (!(m_levelStyles
[i
] == def
.m_levelStyles
[i
]))
113 /// Sets/gets the attributes for the given level
114 void wxRichTextListStyleDefinition::SetLevelAttributes(int i
, const wxTextAttr
& attr
)
116 wxASSERT( (i
>= 0 && i
< 10) );
117 if (i
>= 0 && i
< 10)
118 m_levelStyles
[i
] = attr
;
121 const wxTextAttr
* wxRichTextListStyleDefinition::GetLevelAttributes(int i
) const
123 wxASSERT( (i
>= 0 && i
< 10) );
124 if (i
>= 0 && i
< 10)
125 return & m_levelStyles
[i
];
130 wxTextAttr
* wxRichTextListStyleDefinition::GetLevelAttributes(int i
)
132 wxASSERT( (i
>= 0 && i
< 10) );
133 if (i
>= 0 && i
< 10)
134 return & m_levelStyles
[i
];
139 /// Convenience function for setting the major attributes for a list level specification
140 void wxRichTextListStyleDefinition::SetAttributes(int i
, int leftIndent
, int leftSubIndent
, int bulletStyle
, const wxString
& bulletSymbol
)
142 wxASSERT( (i
>= 0 && i
< 10) );
143 if (i
>= 0 && i
< 10)
147 attr
.SetBulletStyle(bulletStyle
);
148 attr
.SetLeftIndent(leftIndent
, leftSubIndent
);
150 if (!bulletSymbol
.IsEmpty())
152 if (bulletStyle
& wxTEXT_ATTR_BULLET_STYLE_SYMBOL
)
153 attr
.SetBulletText(bulletSymbol
);
155 attr
.SetBulletName(bulletSymbol
);
158 m_levelStyles
[i
] = attr
;
162 /// Finds the level corresponding to the given indentation
163 int wxRichTextListStyleDefinition::FindLevelForIndent(int indent
) const
166 for (i
= 0; i
< 10; i
++)
168 if (indent
< m_levelStyles
[i
].GetLeftIndent())
179 /// Combine the list style with a paragraph style, using the given indent (from which
180 /// an appropriate level is found)
181 wxTextAttr
wxRichTextListStyleDefinition::CombineWithParagraphStyle(int indent
, const wxTextAttr
& paraStyle
, wxRichTextStyleSheet
* styleSheet
)
183 int listLevel
= FindLevelForIndent(indent
);
185 wxTextAttr
attr(*GetLevelAttributes(listLevel
));
186 int oldLeftIndent
= attr
.GetLeftIndent();
187 int oldLeftSubIndent
= attr
.GetLeftSubIndent();
189 // First apply the overall paragraph style, if any
191 attr
.Apply(GetStyleMergedWithBase(styleSheet
));
193 attr
.Apply(GetStyle());
195 // Then apply paragraph style, e.g. from paragraph style definition
196 attr
.Apply(paraStyle
);
198 // We override the indents according to the list definition
199 attr
.SetLeftIndent(oldLeftIndent
, oldLeftSubIndent
);
204 /// Combine the base and list style, using the given indent (from which
205 /// an appropriate level is found)
206 wxTextAttr
wxRichTextListStyleDefinition::GetCombinedStyle(int indent
, wxRichTextStyleSheet
* styleSheet
)
208 int listLevel
= FindLevelForIndent(indent
);
209 return GetCombinedStyleForLevel(listLevel
, styleSheet
);
212 /// Combine the base and list style, using the given indent (from which
213 /// an appropriate level is found)
214 wxTextAttr
wxRichTextListStyleDefinition::GetCombinedStyleForLevel(int listLevel
, wxRichTextStyleSheet
* styleSheet
)
216 wxTextAttr
attr(*GetLevelAttributes(listLevel
));
217 int oldLeftIndent
= attr
.GetLeftIndent();
218 int oldLeftSubIndent
= attr
.GetLeftSubIndent();
220 // Apply the overall paragraph style, if any
222 attr
.Apply(GetStyleMergedWithBase(styleSheet
));
224 attr
.Apply(GetStyle());
226 // We override the indents according to the list definition
227 attr
.SetLeftIndent(oldLeftIndent
, oldLeftSubIndent
);
232 /// Is this a numbered list?
233 bool wxRichTextListStyleDefinition::IsNumbered(int i
) const
235 return (0 != (GetLevelAttributes(i
)->GetFlags() &
236 (wxTEXT_ATTR_BULLET_STYLE_ARABIC
|wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER
|wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER
|
237 wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER
|wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER
)));
244 IMPLEMENT_CLASS(wxRichTextStyleSheet
, wxObject
)
246 wxRichTextStyleSheet::~wxRichTextStyleSheet()
251 m_nextSheet
->m_previousSheet
= m_previousSheet
;
254 m_previousSheet
->m_nextSheet
= m_nextSheet
;
256 m_previousSheet
= NULL
;
261 void wxRichTextStyleSheet::Init()
263 m_previousSheet
= NULL
;
267 /// Add a definition to one of the style lists
268 bool wxRichTextStyleSheet::AddStyle(wxList
& list
, wxRichTextStyleDefinition
* def
)
276 bool wxRichTextStyleSheet::RemoveStyle(wxList
& list
, wxRichTextStyleDefinition
* def
, bool deleteStyle
)
278 wxList::compatibility_iterator node
= list
.Find(def
);
281 wxRichTextStyleDefinition
* def
= (wxRichTextStyleDefinition
*) node
->GetData();
292 bool wxRichTextStyleSheet::RemoveStyle(wxRichTextStyleDefinition
* def
, bool deleteStyle
)
294 if (RemoveParagraphStyle(def
, deleteStyle
))
296 if (RemoveCharacterStyle(def
, deleteStyle
))
298 if (RemoveListStyle(def
, deleteStyle
))
303 /// Find a definition by name
304 wxRichTextStyleDefinition
* wxRichTextStyleSheet::FindStyle(const wxList
& list
, const wxString
& name
, bool recurse
) const
306 for (wxList::compatibility_iterator node
= list
.GetFirst(); node
; node
= node
->GetNext())
308 wxRichTextStyleDefinition
* def
= (wxRichTextStyleDefinition
*) node
->GetData();
309 if (def
->GetName().Lower() == name
.Lower())
313 if (m_nextSheet
&& recurse
)
314 return m_nextSheet
->FindStyle(list
, name
, recurse
);
319 /// Delete all styles
320 void wxRichTextStyleSheet::DeleteStyles()
322 WX_CLEAR_LIST(wxList
, m_characterStyleDefinitions
);
323 WX_CLEAR_LIST(wxList
, m_paragraphStyleDefinitions
);
324 WX_CLEAR_LIST(wxList
, m_listStyleDefinitions
);
327 /// Insert into list of style sheets
328 bool wxRichTextStyleSheet::InsertSheet(wxRichTextStyleSheet
* before
)
330 m_previousSheet
= before
->m_previousSheet
;
331 m_nextSheet
= before
;
333 before
->m_previousSheet
= this;
337 /// Append to list of style sheets
338 bool wxRichTextStyleSheet::AppendSheet(wxRichTextStyleSheet
* after
)
340 wxRichTextStyleSheet
* last
= after
;
341 while (last
&& last
->m_nextSheet
)
343 last
= last
->m_nextSheet
;
348 m_previousSheet
= last
;
349 last
->m_nextSheet
= this;
357 /// Unlink from the list of style sheets
358 void wxRichTextStyleSheet::Unlink()
361 m_previousSheet
->m_nextSheet
= m_nextSheet
;
363 m_nextSheet
->m_previousSheet
= m_previousSheet
;
365 m_previousSheet
= NULL
;
369 /// Add a definition to the character style list
370 bool wxRichTextStyleSheet::AddCharacterStyle(wxRichTextCharacterStyleDefinition
* def
)
372 def
->GetStyle().SetCharacterStyleName(def
->GetName());
373 return AddStyle(m_characterStyleDefinitions
, def
);
376 /// Add a definition to the paragraph style list
377 bool wxRichTextStyleSheet::AddParagraphStyle(wxRichTextParagraphStyleDefinition
* def
)
379 def
->GetStyle().SetParagraphStyleName(def
->GetName());
380 return AddStyle(m_paragraphStyleDefinitions
, def
);
383 /// Add a definition to the list style list
384 bool wxRichTextStyleSheet::AddListStyle(wxRichTextListStyleDefinition
* def
)
386 def
->GetStyle().SetListStyleName(def
->GetName());
387 return AddStyle(m_listStyleDefinitions
, def
);
390 /// Add a definition to the appropriate style list
391 bool wxRichTextStyleSheet::AddStyle(wxRichTextStyleDefinition
* def
)
393 wxRichTextListStyleDefinition
* listDef
= wxDynamicCast(def
, wxRichTextListStyleDefinition
);
395 return AddListStyle(listDef
);
397 wxRichTextParagraphStyleDefinition
* paraDef
= wxDynamicCast(def
, wxRichTextParagraphStyleDefinition
);
399 return AddParagraphStyle(paraDef
);
401 wxRichTextCharacterStyleDefinition
* charDef
= wxDynamicCast(def
, wxRichTextCharacterStyleDefinition
);
403 return AddCharacterStyle(charDef
);
408 /// Find any definition by name
409 wxRichTextStyleDefinition
* wxRichTextStyleSheet::FindStyle(const wxString
& name
, bool recurse
) const
411 wxRichTextListStyleDefinition
* listDef
= FindListStyle(name
, recurse
);
415 wxRichTextParagraphStyleDefinition
* paraDef
= FindParagraphStyle(name
, recurse
);
419 wxRichTextCharacterStyleDefinition
* charDef
= FindCharacterStyle(name
, recurse
);
427 void wxRichTextStyleSheet::Copy(const wxRichTextStyleSheet
& sheet
)
431 wxList::compatibility_iterator node
;
433 for (node
= sheet
.m_characterStyleDefinitions
.GetFirst(); node
; node
= node
->GetNext())
435 wxRichTextCharacterStyleDefinition
* def
= (wxRichTextCharacterStyleDefinition
*) node
->GetData();
436 AddCharacterStyle(new wxRichTextCharacterStyleDefinition(*def
));
439 for (node
= sheet
.m_paragraphStyleDefinitions
.GetFirst(); node
; node
= node
->GetNext())
441 wxRichTextParagraphStyleDefinition
* def
= (wxRichTextParagraphStyleDefinition
*) node
->GetData();
442 AddParagraphStyle(new wxRichTextParagraphStyleDefinition(*def
));
445 for (node
= sheet
.m_listStyleDefinitions
.GetFirst(); node
; node
= node
->GetNext())
447 wxRichTextListStyleDefinition
* def
= (wxRichTextListStyleDefinition
*) node
->GetData();
448 AddListStyle(new wxRichTextListStyleDefinition(*def
));
451 SetName(sheet
.GetName());
452 SetDescription(sheet
.GetDescription());
456 bool wxRichTextStyleSheet::operator==(const wxRichTextStyleSheet
& WXUNUSED(sheet
)) const
465 * wxRichTextStyleListBox: a listbox to display styles.
468 IMPLEMENT_CLASS(wxRichTextStyleListBox
, wxHtmlListBox
)
470 BEGIN_EVENT_TABLE(wxRichTextStyleListBox
, wxHtmlListBox
)
471 EVT_LEFT_DOWN(wxRichTextStyleListBox::OnLeftDown
)
472 EVT_LEFT_DCLICK(wxRichTextStyleListBox::OnLeftDoubleClick
)
473 EVT_IDLE(wxRichTextStyleListBox::OnIdle
)
476 wxRichTextStyleListBox::wxRichTextStyleListBox(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
477 const wxSize
& size
, long style
)
480 Create(parent
, id
, pos
, size
, style
);
483 bool wxRichTextStyleListBox::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
484 const wxSize
& size
, long style
)
486 return wxHtmlListBox::Create(parent
, id
, pos
, size
, style
);
489 wxRichTextStyleListBox::~wxRichTextStyleListBox()
493 /// Returns the HTML for this item
494 wxString
wxRichTextStyleListBox::OnGetItem(size_t n
) const
496 if (!GetStyleSheet())
497 return wxEmptyString
;
499 wxRichTextStyleDefinition
* def
= GetStyle(n
);
501 return CreateHTML(def
);
503 return wxEmptyString
;
506 // Get style for index
507 wxRichTextStyleDefinition
* wxRichTextStyleListBox::GetStyle(size_t i
) const
509 if (!GetStyleSheet())
512 if (i
>= m_styleNames
.GetCount() /* || i < 0 */ )
515 return GetStyleSheet()->FindStyle(m_styleNames
[i
]);
519 void wxRichTextStyleListBox::UpdateStyles()
523 SetSelection(wxNOT_FOUND
);
525 m_styleNames
.Clear();
528 if (GetStyleType() == wxRICHTEXT_STYLE_ALL
|| GetStyleType() == wxRICHTEXT_STYLE_PARAGRAPH
)
530 for (i
= 0; i
< GetStyleSheet()->GetParagraphStyleCount(); i
++)
531 m_styleNames
.Add(GetStyleSheet()->GetParagraphStyle(i
)->GetName());
533 if (GetStyleType() == wxRICHTEXT_STYLE_ALL
|| GetStyleType() == wxRICHTEXT_STYLE_CHARACTER
)
535 for (i
= 0; i
< GetStyleSheet()->GetCharacterStyleCount(); i
++)
536 m_styleNames
.Add(GetStyleSheet()->GetCharacterStyle(i
)->GetName());
538 if (GetStyleType() == wxRICHTEXT_STYLE_ALL
|| GetStyleType() == wxRICHTEXT_STYLE_LIST
)
540 for (i
= 0; i
< GetStyleSheet()->GetListStyleCount(); i
++)
541 m_styleNames
.Add(GetStyleSheet()->GetListStyle(i
)->GetName());
545 SetItemCount(m_styleNames
.GetCount());
549 if (GetItemCount() > 0)
557 // Get index for style name
558 int wxRichTextStyleListBox::GetIndexForStyle(const wxString
& name
) const
560 return m_styleNames
.Index(name
);
563 /// Set selection for string
564 int wxRichTextStyleListBox::SetStyleSelection(const wxString
& name
)
566 int i
= GetIndexForStyle(name
);
572 // Convert a colour to a 6-digit hex string
573 static wxString
ColourToHexString(const wxColour
& col
)
577 hex
+= wxDecToHex(col
.Red());
578 hex
+= wxDecToHex(col
.Green());
579 hex
+= wxDecToHex(col
.Blue());
584 /// Creates a suitable HTML fragment for a definition
585 wxString
wxRichTextStyleListBox::CreateHTML(wxRichTextStyleDefinition
* def
) const
587 // TODO: indicate list format for list style types
591 bool isCentred
= false;
593 wxTextAttr
attr(def
->GetStyleMergedWithBase(GetStyleSheet()));
595 if (attr
.HasAlignment() && attr
.GetAlignment() == wxTEXT_ALIGNMENT_CENTRE
)
599 str
<< wxT("<center>");
602 str
<< wxT("<table><tr>");
604 if (attr
.GetLeftIndent() > 0)
606 wxClientDC
dc((wxWindow
*) this);
608 str
<< wxT("<td width=") << wxMin(50, (ConvertTenthsMMToPixels(dc
, attr
.GetLeftIndent())/2)) << wxT("></td>");
612 str
<< wxT("<td nowrap align=\"center\">");
614 str
<< wxT("<td nowrap>");
622 int stdFontSize
= 12;
623 int thisFontSize
= ((attr
.GetFlags() & wxTEXT_ATTR_FONT_SIZE
) != 0) ? attr
.GetFontSize() : stdFontSize
;
625 if (thisFontSize
< stdFontSize
)
627 else if (thisFontSize
> stdFontSize
)
632 str
<< wxT(" size=") << size
;
634 if (!attr
.GetFontFaceName().IsEmpty())
635 str
<< wxT(" face=\"") << attr
.GetFontFaceName() << wxT("\"");
637 if (attr
.GetTextColour().Ok())
638 str
<< wxT(" color=\"#") << ColourToHexString(attr
.GetTextColour()) << wxT("\"");
642 bool hasBold
= false;
643 bool hasItalic
= false;
644 bool hasUnderline
= false;
646 if (attr
.GetFontWeight() == wxBOLD
)
648 if (attr
.GetFontStyle() == wxITALIC
)
650 if (attr
.GetFontUnderlined())
660 str
+= def
->GetName();
670 str
<< wxT("</centre>");
672 str
<< wxT("</font>");
674 str
<< wxT("</td></tr></table>");
677 str
<< wxT("</center>");
682 // Convert units in tends of a millimetre to device units
683 int wxRichTextStyleListBox::ConvertTenthsMMToPixels(wxDC
& dc
, int units
) const
685 int ppi
= dc
.GetPPI().x
;
687 // There are ppi pixels in 254.1 "1/10 mm"
689 double pixels
= ((double) units
* (double)ppi
) / 254.1;
694 void wxRichTextStyleListBox::OnLeftDown(wxMouseEvent
& event
)
696 wxVListBox::OnLeftDown(event
);
698 int item
= HitTest(event
.GetPosition());
699 if (item
!= wxNOT_FOUND
&& GetApplyOnSelection())
703 void wxRichTextStyleListBox::OnLeftDoubleClick(wxMouseEvent
& event
)
705 wxVListBox::OnLeftDown(event
);
707 int item
= HitTest(event
.GetPosition());
708 if (item
!= wxNOT_FOUND
&& !GetApplyOnSelection())
712 /// Helper for listbox and combo control
713 wxString
wxRichTextStyleListBox::GetStyleToShowInIdleTime(wxRichTextCtrl
* ctrl
, wxRichTextStyleType styleType
)
715 int adjustedCaretPos
= ctrl
->GetAdjustedCaretPosition(ctrl
->GetCaretPosition());
720 ctrl
->GetStyle(adjustedCaretPos
, attr
);
722 // Take into account current default style just chosen by user
723 if (ctrl
->IsDefaultStyleShowing())
725 wxRichTextApplyStyle(attr
, ctrl
->GetDefaultStyleEx());
727 if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_CHARACTER
) &&
728 !attr
.GetCharacterStyleName().IsEmpty())
729 styleName
= attr
.GetCharacterStyleName();
730 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_PARAGRAPH
) &&
731 !attr
.GetParagraphStyleName().IsEmpty())
732 styleName
= attr
.GetParagraphStyleName();
733 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_LIST
) &&
734 !attr
.GetListStyleName().IsEmpty())
735 styleName
= attr
.GetListStyleName();
737 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_CHARACTER
) &&
738 !attr
.GetCharacterStyleName().IsEmpty())
740 styleName
= attr
.GetCharacterStyleName();
742 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_PARAGRAPH
) &&
743 !attr
.GetParagraphStyleName().IsEmpty())
745 styleName
= attr
.GetParagraphStyleName();
747 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_LIST
) &&
748 !attr
.GetListStyleName().IsEmpty())
750 styleName
= attr
.GetListStyleName();
756 /// Auto-select from style under caret in idle time
757 void wxRichTextStyleListBox::OnIdle(wxIdleEvent
& event
)
759 if (CanAutoSetSelection() && GetRichTextCtrl() && wxWindow::FindFocus() != this)
761 wxString styleName
= GetStyleToShowInIdleTime(GetRichTextCtrl(), GetStyleType());
763 int sel
= GetSelection();
764 if (!styleName
.IsEmpty())
766 // Don't do the selection if it's already set
767 if (sel
== GetIndexForStyle(styleName
))
770 SetStyleSelection(styleName
);
779 void wxRichTextStyleListBox::ApplyStyle(int item
)
781 if ( item
!= wxNOT_FOUND
)
783 wxRichTextStyleDefinition
* def
= GetStyle(item
);
784 if (def
&& GetRichTextCtrl())
786 GetRichTextCtrl()->ApplyStyle(def
);
787 GetRichTextCtrl()->SetFocus();
793 * wxRichTextStyleListCtrl class: manages a listbox and a choice control to
794 * switch shown style types
797 IMPLEMENT_CLASS(wxRichTextStyleListCtrl
, wxControl
)
799 BEGIN_EVENT_TABLE(wxRichTextStyleListCtrl
, wxControl
)
800 EVT_CHOICE(wxID_ANY
, wxRichTextStyleListCtrl::OnChooseType
)
801 EVT_SIZE(wxRichTextStyleListCtrl::OnSize
)
804 wxRichTextStyleListCtrl::wxRichTextStyleListCtrl(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
805 const wxSize
& size
, long style
)
808 Create(parent
, id
, pos
, size
, style
);
811 bool wxRichTextStyleListCtrl::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
812 const wxSize
& size
, long style
)
814 if ((style
& wxBORDER_MASK
) == wxBORDER_DEFAULT
)
815 style
|= wxBORDER_THEME
;
817 wxControl::Create(parent
, id
, pos
, size
, style
);
819 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
));
820 if (size
!= wxDefaultSize
)
821 SetInitialSize(size
);
823 bool showSelector
= ((style
& wxRICHTEXTSTYLELIST_HIDE_TYPE_SELECTOR
) == 0);
825 wxBorder listBoxStyle
;
827 listBoxStyle
= wxBORDER_THEME
;
829 listBoxStyle
= wxBORDER_NONE
;
831 m_styleListBox
= new wxRichTextStyleListBox(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, listBoxStyle
);
833 wxBoxSizer
* boxSizer
= new wxBoxSizer(wxVERTICAL
);
837 wxArrayString choices
;
838 choices
.Add(_("All styles"));
839 choices
.Add(_("Paragraph styles"));
840 choices
.Add(_("Character styles"));
841 choices
.Add(_("List styles"));
843 m_styleChoice
= new wxChoice(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, choices
);
845 boxSizer
->Add(m_styleListBox
, 1, wxALL
|wxEXPAND
, 5);
846 boxSizer
->Add(m_styleChoice
, 0, wxLEFT
|wxRIGHT
|wxBOTTOM
|wxEXPAND
, 5);
850 boxSizer
->Add(m_styleListBox
, 1, wxALL
|wxEXPAND
, 0);
860 int i
= StyleTypeToIndex(m_styleListBox
->GetStyleType());
861 m_styleChoice
->SetSelection(i
);
864 m_dontUpdate
= false;
869 wxRichTextStyleListCtrl::~wxRichTextStyleListCtrl()
874 /// React to style type choice
875 void wxRichTextStyleListCtrl::OnChooseType(wxCommandEvent
& event
)
877 if (event
.GetEventObject() != m_styleChoice
)
884 wxRichTextStyleListBox::wxRichTextStyleType styleType
= StyleIndexToType(event
.GetSelection());
885 m_styleListBox
->SetStyleType(styleType
);
889 /// Lay out the controls
890 void wxRichTextStyleListCtrl::OnSize(wxSizeEvent
& WXUNUSED(event
))
896 /// Get the choice index for style type
897 int wxRichTextStyleListCtrl::StyleTypeToIndex(wxRichTextStyleListBox::wxRichTextStyleType styleType
)
899 if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
)
903 else if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH
)
907 else if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER
)
911 else if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST
)
918 /// Get the style type for choice index
919 wxRichTextStyleListBox::wxRichTextStyleType
wxRichTextStyleListCtrl::StyleIndexToType(int i
)
922 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH
;
924 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER
;
926 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST
;
928 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
;
931 /// Associates the control with a style manager
932 void wxRichTextStyleListCtrl::SetStyleSheet(wxRichTextStyleSheet
* styleSheet
)
935 m_styleListBox
->SetStyleSheet(styleSheet
);
938 wxRichTextStyleSheet
* wxRichTextStyleListCtrl::GetStyleSheet() const
941 return m_styleListBox
->GetStyleSheet();
946 /// Associates the control with a wxRichTextCtrl
947 void wxRichTextStyleListCtrl::SetRichTextCtrl(wxRichTextCtrl
* ctrl
)
950 m_styleListBox
->SetRichTextCtrl(ctrl
);
953 wxRichTextCtrl
* wxRichTextStyleListCtrl::GetRichTextCtrl() const
956 return m_styleListBox
->GetRichTextCtrl();
961 /// Set/get the style type to display
962 void wxRichTextStyleListCtrl::SetStyleType(wxRichTextStyleListBox::wxRichTextStyleType styleType
)
964 if ( !m_styleListBox
)
967 m_styleListBox
->SetStyleType(styleType
);
973 int i
= StyleTypeToIndex(m_styleListBox
->GetStyleType());
974 m_styleChoice
->SetSelection(i
);
977 m_dontUpdate
= false;
980 wxRichTextStyleListBox::wxRichTextStyleType
wxRichTextStyleListCtrl::GetStyleType() const
983 return m_styleListBox
->GetStyleType();
985 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
;
988 /// Updates the style list box
989 void wxRichTextStyleListCtrl::UpdateStyles()
992 m_styleListBox
->UpdateStyles();
998 * Style drop-down for a wxComboCtrl
1002 BEGIN_EVENT_TABLE(wxRichTextStyleComboPopup
, wxRichTextStyleListBox
)
1003 EVT_MOTION(wxRichTextStyleComboPopup::OnMouseMove
)
1004 EVT_LEFT_DOWN(wxRichTextStyleComboPopup::OnMouseClick
)
1007 bool wxRichTextStyleComboPopup::Create( wxWindow
* parent
)
1009 int borderStyle
= GetDefaultBorder();
1010 if (borderStyle
== wxBORDER_SUNKEN
)
1011 borderStyle
= wxBORDER_SIMPLE
;
1013 return wxRichTextStyleListBox::Create(parent
, wxID_ANY
,
1014 wxPoint(0,0), wxDefaultSize
,
1018 void wxRichTextStyleComboPopup::SetStringValue( const wxString
& s
)
1020 m_value
= SetStyleSelection(s
);
1023 wxString
wxRichTextStyleComboPopup::GetStringValue() const
1028 wxRichTextStyleDefinition
* def
= GetStyle(sel
);
1030 return def
->GetName();
1032 return wxEmptyString
;
1036 // Popup event handlers
1039 // Mouse hot-tracking
1040 void wxRichTextStyleComboPopup::OnMouseMove(wxMouseEvent
& event
)
1042 // Move selection to cursor if it is inside the popup
1044 int itemHere
= wxRichTextStyleListBox::HitTest(event
.GetPosition());
1045 if ( itemHere
>= 0 )
1047 wxRichTextStyleListBox::SetSelection(itemHere
);
1048 m_itemHere
= itemHere
;
1053 // On mouse left, set the value and close the popup
1054 void wxRichTextStyleComboPopup::OnMouseClick(wxMouseEvent
& WXUNUSED(event
))
1056 if (m_itemHere
>= 0)
1057 m_value
= m_itemHere
;
1059 // Ordering is important, so we don't dismiss this popup accidentally
1060 // by setting the focus elsewhere e.g. in ApplyStyle
1063 if (m_itemHere
>= 0)
1064 wxRichTextStyleListBox::ApplyStyle(m_itemHere
);
1068 * wxRichTextStyleComboCtrl
1069 * A combo for applying styles.
1072 IMPLEMENT_CLASS(wxRichTextStyleComboCtrl
, wxComboCtrl
)
1074 BEGIN_EVENT_TABLE(wxRichTextStyleComboCtrl
, wxComboCtrl
)
1075 EVT_IDLE(wxRichTextStyleComboCtrl::OnIdle
)
1078 bool wxRichTextStyleComboCtrl::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
1079 const wxSize
& size
, long style
)
1081 if (!wxComboCtrl::Create(parent
, id
, wxEmptyString
, pos
, size
, style
))
1084 SetPopupMaxHeight(400);
1086 m_stylePopup
= new wxRichTextStyleComboPopup
;
1088 SetPopupControl(m_stylePopup
);
1093 /// Auto-select from style under caret in idle time
1095 // TODO: must be able to show italic, bold, combinations
1096 // in style box. Do we have a concept of automatic, temporary
1097 // styles that are added whenever we wish to show a style
1098 // that doesn't exist already? E.g. "Bold, Italic, Underline".
1099 // Word seems to generate these things on the fly.
1100 // If there's a named style already, it uses e.g. Heading1 + Bold, Italic
1101 // If you unembolden text in a style that has bold, it uses the
1103 // TODO: order styles alphabetically. This means indexes can change,
1104 // so need a different way to specify selections, i.e. by name.
1106 void wxRichTextStyleComboCtrl::OnIdle(wxIdleEvent
& event
)
1110 if ( !m_stylePopup
)
1113 wxRichTextCtrl
* const richtext
= GetRichTextCtrl();
1117 if ( !IsPopupShown() && wxWindow::FindFocus() != this )
1119 wxString styleName
=
1120 wxRichTextStyleListBox::GetStyleToShowInIdleTime(richtext
, m_stylePopup
->GetStyleType());
1122 wxString currentValue
= GetValue();
1123 if (!styleName
.IsEmpty())
1125 // Don't do the selection if it's already set
1126 if (currentValue
== styleName
)
1129 SetValue(styleName
);
1131 else if (!currentValue
.IsEmpty())
1132 SetValue(wxEmptyString
);