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
);
57 * Paragraph style definition
60 void wxRichTextParagraphStyleDefinition::Copy(const wxRichTextParagraphStyleDefinition
& def
)
62 wxRichTextStyleDefinition::Copy(def
);
64 m_nextStyle
= def
.m_nextStyle
;
67 bool wxRichTextParagraphStyleDefinition::operator ==(const wxRichTextParagraphStyleDefinition
& def
) const
69 return (Eq(def
) && m_nextStyle
== def
.m_nextStyle
);
73 * List style definition
76 void wxRichTextListStyleDefinition::Copy(const wxRichTextListStyleDefinition
& def
)
78 wxRichTextParagraphStyleDefinition::Copy(def
);
81 for (i
= 0; i
< 10; i
++)
82 m_levelStyles
[i
] = def
.m_levelStyles
[i
];
85 bool wxRichTextListStyleDefinition::operator ==(const wxRichTextListStyleDefinition
& def
) const
90 for (i
= 0; i
< 10; i
++)
91 if (!(m_levelStyles
[i
] == def
.m_levelStyles
[i
]))
97 /// Sets/gets the attributes for the given level
98 void wxRichTextListStyleDefinition::SetLevelAttributes(int i
, const wxRichTextAttr
& attr
)
100 wxASSERT( (i
>= 0 && i
< 10) );
101 if (i
>= 0 && i
< 10)
102 m_levelStyles
[i
] = attr
;
105 const wxRichTextAttr
* wxRichTextListStyleDefinition::GetLevelAttributes(int i
) const
107 wxASSERT( (i
>= 0 && i
< 10) );
108 if (i
>= 0 && i
< 10)
109 return & m_levelStyles
[i
];
114 wxRichTextAttr
* wxRichTextListStyleDefinition::GetLevelAttributes(int i
)
116 wxASSERT( (i
>= 0 && i
< 10) );
117 if (i
>= 0 && i
< 10)
118 return & m_levelStyles
[i
];
123 /// Convenience function for setting the major attributes for a list level specification
124 void wxRichTextListStyleDefinition::SetAttributes(int i
, int leftIndent
, int leftSubIndent
, int bulletStyle
, const wxString
& bulletSymbol
)
126 wxASSERT( (i
>= 0 && i
< 10) );
127 if (i
>= 0 && i
< 10)
131 attr
.SetBulletStyle(bulletStyle
);
132 attr
.SetLeftIndent(leftIndent
, leftSubIndent
);
134 if (!bulletSymbol
.IsEmpty())
136 if (bulletStyle
& wxTEXT_ATTR_BULLET_STYLE_SYMBOL
)
137 attr
.SetBulletText(bulletSymbol
);
139 attr
.SetBulletName(bulletSymbol
);
142 m_levelStyles
[i
] = attr
;
146 /// Finds the level corresponding to the given indentation
147 int wxRichTextListStyleDefinition::FindLevelForIndent(int indent
) const
150 for (i
= 0; i
< 10; i
++)
152 if (indent
< m_levelStyles
[i
].GetLeftIndent())
163 /// Combine the list style with a paragraph style, using the given indent (from which
164 /// an appropriate level is found)
165 wxRichTextAttr
wxRichTextListStyleDefinition::CombineWithParagraphStyle(int indent
, const wxRichTextAttr
& paraStyle
)
167 int listLevel
= FindLevelForIndent(indent
);
169 wxRichTextAttr
attr(*GetLevelAttributes(listLevel
));
170 int oldLeftIndent
= attr
.GetLeftIndent();
171 int oldLeftSubIndent
= attr
.GetLeftSubIndent();
173 // First apply the overall paragraph style, if any
174 wxRichTextApplyStyle(attr
, GetStyle());
176 // Then apply paragraph style, e.g. from paragraph style definition
177 wxRichTextApplyStyle(attr
, paraStyle
);
179 // We override the indents according to the list definition
180 attr
.SetLeftIndent(oldLeftIndent
, oldLeftSubIndent
);
185 /// Combine the base and list style, using the given indent (from which
186 /// an appropriate level is found)
187 wxRichTextAttr
wxRichTextListStyleDefinition::GetCombinedStyle(int indent
)
189 int listLevel
= FindLevelForIndent(indent
);
190 return GetCombinedStyleForLevel(listLevel
);
193 /// Combine the base and list style, using the given indent (from which
194 /// an appropriate level is found)
195 wxRichTextAttr
wxRichTextListStyleDefinition::GetCombinedStyleForLevel(int listLevel
)
197 wxRichTextAttr
attr(*GetLevelAttributes(listLevel
));
198 int oldLeftIndent
= attr
.GetLeftIndent();
199 int oldLeftSubIndent
= attr
.GetLeftSubIndent();
201 // Apply the overall paragraph style, if any
202 wxRichTextApplyStyle(attr
, GetStyle());
204 // We override the indents according to the list definition
205 attr
.SetLeftIndent(oldLeftIndent
, oldLeftSubIndent
);
210 /// Is this a numbered list?
211 bool wxRichTextListStyleDefinition::IsNumbered(int i
) const
213 return (0 != (GetLevelAttributes(i
)->GetFlags() &
214 (wxTEXT_ATTR_BULLET_STYLE_ARABIC
|wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER
|wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER
|
215 wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER
|wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER
)));
222 IMPLEMENT_CLASS(wxRichTextStyleSheet
, wxObject
)
224 wxRichTextStyleSheet::~wxRichTextStyleSheet()
229 m_nextSheet
->m_previousSheet
= m_previousSheet
;
232 m_previousSheet
->m_nextSheet
= m_nextSheet
;
234 m_previousSheet
= NULL
;
239 void wxRichTextStyleSheet::Init()
241 m_previousSheet
= NULL
;
245 /// Add a definition to one of the style lists
246 bool wxRichTextStyleSheet::AddStyle(wxList
& list
, wxRichTextStyleDefinition
* def
)
254 bool wxRichTextStyleSheet::RemoveStyle(wxList
& list
, wxRichTextStyleDefinition
* def
, bool deleteStyle
)
256 wxList::compatibility_iterator node
= list
.Find(def
);
259 wxRichTextStyleDefinition
* def
= (wxRichTextStyleDefinition
*) node
->GetData();
269 /// Find a definition by name
270 wxRichTextStyleDefinition
* wxRichTextStyleSheet::FindStyle(const wxList
& list
, const wxString
& name
, bool recurse
) const
272 for (wxList::compatibility_iterator node
= list
.GetFirst(); node
; node
= node
->GetNext())
274 wxRichTextStyleDefinition
* def
= (wxRichTextStyleDefinition
*) node
->GetData();
275 if (def
->GetName().Lower() == name
.Lower())
279 if (m_nextSheet
&& recurse
)
280 return m_nextSheet
->FindStyle(list
, name
, recurse
);
285 /// Delete all styles
286 void wxRichTextStyleSheet::DeleteStyles()
288 WX_CLEAR_LIST(wxList
, m_characterStyleDefinitions
);
289 WX_CLEAR_LIST(wxList
, m_paragraphStyleDefinitions
);
290 WX_CLEAR_LIST(wxList
, m_listStyleDefinitions
);
293 /// Insert into list of style sheets
294 bool wxRichTextStyleSheet::InsertSheet(wxRichTextStyleSheet
* before
)
296 m_previousSheet
= before
->m_previousSheet
;
297 m_nextSheet
= before
;
299 before
->m_previousSheet
= this;
303 /// Append to list of style sheets
304 bool wxRichTextStyleSheet::AppendSheet(wxRichTextStyleSheet
* after
)
306 wxRichTextStyleSheet
* last
= after
;
307 while (last
&& last
->m_nextSheet
)
309 last
= last
->m_nextSheet
;
314 m_previousSheet
= last
;
315 last
->m_nextSheet
= this;
323 /// Unlink from the list of style sheets
324 void wxRichTextStyleSheet::Unlink()
327 m_previousSheet
->m_nextSheet
= m_nextSheet
;
329 m_nextSheet
->m_previousSheet
= m_previousSheet
;
331 m_previousSheet
= NULL
;
335 /// Add a definition to the character style list
336 bool wxRichTextStyleSheet::AddCharacterStyle(wxRichTextCharacterStyleDefinition
* def
)
338 def
->GetStyle().SetCharacterStyleName(def
->GetName());
339 return AddStyle(m_characterStyleDefinitions
, def
);
342 /// Add a definition to the paragraph style list
343 bool wxRichTextStyleSheet::AddParagraphStyle(wxRichTextParagraphStyleDefinition
* def
)
345 def
->GetStyle().SetParagraphStyleName(def
->GetName());
346 return AddStyle(m_paragraphStyleDefinitions
, def
);
349 /// Add a definition to the list style list
350 bool wxRichTextStyleSheet::AddListStyle(wxRichTextListStyleDefinition
* def
)
352 def
->GetStyle().SetListStyleName(def
->GetName());
353 return AddStyle(m_listStyleDefinitions
, def
);
357 void wxRichTextStyleSheet::Copy(const wxRichTextStyleSheet
& sheet
)
361 wxList::compatibility_iterator node
;
363 for (node
= sheet
.m_characterStyleDefinitions
.GetFirst(); node
; node
= node
->GetNext())
365 wxRichTextCharacterStyleDefinition
* def
= (wxRichTextCharacterStyleDefinition
*) node
->GetData();
366 AddCharacterStyle(new wxRichTextCharacterStyleDefinition(*def
));
369 for (node
= sheet
.m_paragraphStyleDefinitions
.GetFirst(); node
; node
= node
->GetNext())
371 wxRichTextParagraphStyleDefinition
* def
= (wxRichTextParagraphStyleDefinition
*) node
->GetData();
372 AddParagraphStyle(new wxRichTextParagraphStyleDefinition(*def
));
375 for (node
= sheet
.m_listStyleDefinitions
.GetFirst(); node
; node
= node
->GetNext())
377 wxRichTextListStyleDefinition
* def
= (wxRichTextListStyleDefinition
*) node
->GetData();
378 AddListStyle(new wxRichTextListStyleDefinition(*def
));
381 SetName(sheet
.GetName());
382 SetDescription(sheet
.GetDescription());
386 bool wxRichTextStyleSheet::operator==(const wxRichTextStyleSheet
& WXUNUSED(sheet
)) const
395 * wxRichTextStyleListBox: a listbox to display styles.
398 IMPLEMENT_CLASS(wxRichTextStyleListBox
, wxHtmlListBox
)
400 BEGIN_EVENT_TABLE(wxRichTextStyleListBox
, wxHtmlListBox
)
401 EVT_LEFT_DOWN(wxRichTextStyleListBox::OnLeftDown
)
402 EVT_LEFT_DCLICK(wxRichTextStyleListBox::OnLeftDoubleClick
)
403 EVT_IDLE(wxRichTextStyleListBox::OnIdle
)
406 wxRichTextStyleListBox::wxRichTextStyleListBox(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
407 const wxSize
& size
, long style
)
410 Create(parent
, id
, pos
, size
, style
);
413 bool wxRichTextStyleListBox::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
414 const wxSize
& size
, long style
)
416 return wxHtmlListBox::Create(parent
, id
, pos
, size
, style
);
419 wxRichTextStyleListBox::~wxRichTextStyleListBox()
423 /// Returns the HTML for this item
424 wxString
wxRichTextStyleListBox::OnGetItem(size_t n
) const
426 if (!GetStyleSheet())
427 return wxEmptyString
;
429 wxRichTextStyleDefinition
* def
= GetStyle(n
);
431 return CreateHTML(def
);
433 return wxEmptyString
;
436 // Get style for index
437 wxRichTextStyleDefinition
* wxRichTextStyleListBox::GetStyle(size_t i
) const
439 if (!GetStyleSheet())
442 if (GetStyleType() == wxRICHTEXT_STYLE_ALL
)
444 // First paragraph styles, then character, then list
445 if (i
< GetStyleSheet()->GetParagraphStyleCount())
446 return GetStyleSheet()->GetParagraphStyle(i
);
448 if ((i
- GetStyleSheet()->GetParagraphStyleCount()) < GetStyleSheet()->GetCharacterStyleCount())
449 return GetStyleSheet()->GetCharacterStyle(i
- GetStyleSheet()->GetParagraphStyleCount());
451 if ((i
- GetStyleSheet()->GetParagraphStyleCount() - GetStyleSheet()->GetCharacterStyleCount()) < GetStyleSheet()->GetListStyleCount())
452 return GetStyleSheet()->GetListStyle(i
- GetStyleSheet()->GetParagraphStyleCount() - GetStyleSheet()->GetCharacterStyleCount());
454 else if ((GetStyleType() == wxRICHTEXT_STYLE_PARAGRAPH
) && (i
< GetStyleSheet()->GetParagraphStyleCount()))
456 return GetStyleSheet()->GetParagraphStyle(i
);
458 else if ((GetStyleType() == wxRICHTEXT_STYLE_CHARACTER
) && (i
< GetStyleSheet()->GetCharacterStyleCount()))
460 return GetStyleSheet()->GetCharacterStyle(i
);
462 else if ((GetStyleType() == wxRICHTEXT_STYLE_LIST
) && (i
< GetStyleSheet()->GetListStyleCount()))
464 return GetStyleSheet()->GetListStyle(i
);
471 void wxRichTextStyleListBox::UpdateStyles()
475 SetSelection(wxNOT_FOUND
);
477 if (GetStyleType() == wxRICHTEXT_STYLE_ALL
)
478 SetItemCount(GetStyleSheet()->GetParagraphStyleCount()+GetStyleSheet()->GetCharacterStyleCount()+GetStyleSheet()->GetListStyleCount());
479 else if (GetStyleType() == wxRICHTEXT_STYLE_PARAGRAPH
)
480 SetItemCount(GetStyleSheet()->GetParagraphStyleCount());
481 else if (GetStyleType() == wxRICHTEXT_STYLE_CHARACTER
)
482 SetItemCount(GetStyleSheet()->GetCharacterStyleCount());
483 else if (GetStyleType() == wxRICHTEXT_STYLE_LIST
)
484 SetItemCount(GetStyleSheet()->GetListStyleCount());
488 if (GetItemCount() > 0)
496 // Get index for style name
497 int wxRichTextStyleListBox::GetIndexForStyle(const wxString
& name
) const
501 int count
= GetItemCount();
504 for (i
= 0; i
< (int) count
; i
++)
506 wxRichTextStyleDefinition
* def
= GetStyle(i
);
507 if (def
->GetName() == name
)
514 /// Set selection for string
515 int wxRichTextStyleListBox::SetStyleSelection(const wxString
& name
)
517 int i
= GetIndexForStyle(name
);
523 // Convert a colour to a 6-digit hex string
524 static wxString
ColourToHexString(const wxColour
& col
)
528 hex
+= wxDecToHex(col
.Red());
529 hex
+= wxDecToHex(col
.Green());
530 hex
+= wxDecToHex(col
.Blue());
535 /// Creates a suitable HTML fragment for a definition
536 wxString
wxRichTextStyleListBox::CreateHTML(wxRichTextStyleDefinition
* def
) const
538 // TODO: indicate list format for list style types
542 bool isCentred
= false;
544 if (def
->GetStyle().HasAlignment() && def
->GetStyle().GetAlignment() == wxTEXT_ALIGNMENT_CENTRE
)
548 str
<< wxT("<center>");
551 str
<< wxT("<table><tr>");
553 if (def
->GetStyle().GetLeftIndent() > 0)
555 wxClientDC
dc((wxWindow
*) this);
557 str
<< wxT("<td width=") << wxMin(50, (ConvertTenthsMMToPixels(dc
, def
->GetStyle().GetLeftIndent())/2)) << wxT("></td>");
561 str
<< wxT("<td nowrap align=\"center\">");
563 str
<< wxT("<td nowrap>");
571 int stdFontSize
= 12;
572 int thisFontSize
= ((def
->GetStyle().GetFlags() & wxTEXT_ATTR_FONT_SIZE
) != 0) ? def
->GetStyle().GetFontSize() : stdFontSize
;
574 if (thisFontSize
< stdFontSize
)
576 else if (thisFontSize
> stdFontSize
)
581 str
<< wxT(" size=") << size
;
583 if (!def
->GetStyle().GetFontFaceName().IsEmpty())
584 str
<< wxT(" face=\"") << def
->GetStyle().GetFontFaceName() << wxT("\"");
586 if (def
->GetStyle().GetTextColour().Ok())
587 str
<< wxT(" color=\"#") << ColourToHexString(def
->GetStyle().GetTextColour()) << wxT("\"");
591 bool hasBold
= false;
592 bool hasItalic
= false;
593 bool hasUnderline
= false;
595 if (def
->GetStyle().GetFontWeight() == wxBOLD
)
597 if (def
->GetStyle().GetFontStyle() == wxITALIC
)
599 if (def
->GetStyle().GetFontUnderlined())
609 str
+= def
->GetName();
619 str
<< wxT("</centre>");
621 str
<< wxT("</font>");
623 str
<< wxT("</td></tr></table>");
626 str
<< wxT("</center>");
631 // Convert units in tends of a millimetre to device units
632 int wxRichTextStyleListBox::ConvertTenthsMMToPixels(wxDC
& dc
, int units
) const
634 int ppi
= dc
.GetPPI().x
;
636 // There are ppi pixels in 254.1 "1/10 mm"
638 double pixels
= ((double) units
* (double)ppi
) / 254.1;
643 void wxRichTextStyleListBox::OnLeftDown(wxMouseEvent
& event
)
645 wxVListBox::OnLeftDown(event
);
647 int item
= HitTest(event
.GetPosition());
648 if (item
!= wxNOT_FOUND
&& GetApplyOnSelection())
652 void wxRichTextStyleListBox::OnLeftDoubleClick(wxMouseEvent
& event
)
654 wxVListBox::OnLeftDown(event
);
656 int item
= HitTest(event
.GetPosition());
657 if (item
!= wxNOT_FOUND
&& !GetApplyOnSelection())
661 /// Helper for listbox and combo control
662 wxString
wxRichTextStyleListBox::GetStyleToShowInIdleTime(wxRichTextCtrl
* ctrl
, wxRichTextStyleType styleType
)
664 int adjustedCaretPos
= ctrl
->GetAdjustedCaretPosition(ctrl
->GetCaretPosition());
666 wxRichTextParagraph
* para
= ctrl
->GetBuffer().GetParagraphAtPosition(adjustedCaretPos
);
667 wxRichTextObject
* obj
= ctrl
->GetBuffer().GetLeafObjectAtPosition(adjustedCaretPos
);
671 // Take into account current default style just chosen by user
672 if (ctrl
->IsDefaultStyleShowing())
674 if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_CHARACTER
) &&
675 !ctrl
->GetDefaultStyleEx().GetCharacterStyleName().IsEmpty())
676 styleName
= ctrl
->GetDefaultStyleEx().GetCharacterStyleName();
677 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_PARAGRAPH
) &&
678 !ctrl
->GetDefaultStyleEx().GetParagraphStyleName().IsEmpty())
679 styleName
= ctrl
->GetDefaultStyleEx().GetParagraphStyleName();
680 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_LIST
) &&
681 !ctrl
->GetDefaultStyleEx().GetListStyleName().IsEmpty())
682 styleName
= ctrl
->GetDefaultStyleEx().GetListStyleName();
684 else if (obj
&& (styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_CHARACTER
) &&
685 !obj
->GetAttributes().GetCharacterStyleName().IsEmpty())
687 styleName
= obj
->GetAttributes().GetCharacterStyleName();
689 else if (para
&& (styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_PARAGRAPH
) &&
690 !para
->GetAttributes().GetParagraphStyleName().IsEmpty())
692 styleName
= para
->GetAttributes().GetParagraphStyleName();
694 else if (para
&& (styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_LIST
) &&
695 !para
->GetAttributes().GetListStyleName().IsEmpty())
697 styleName
= para
->GetAttributes().GetListStyleName();
703 /// Auto-select from style under caret in idle time
704 void wxRichTextStyleListBox::OnIdle(wxIdleEvent
& event
)
706 if (CanAutoSetSelection() && GetRichTextCtrl() && wxWindow::FindFocus() != this)
708 wxString styleName
= GetStyleToShowInIdleTime(GetRichTextCtrl(), GetStyleType());
710 int sel
= GetSelection();
711 if (!styleName
.IsEmpty())
713 // Don't do the selection if it's already set
714 if (sel
== GetIndexForStyle(styleName
))
717 SetStyleSelection(styleName
);
726 void wxRichTextStyleListBox::ApplyStyle(int item
)
728 if ( item
!= wxNOT_FOUND
)
730 wxRichTextStyleDefinition
* def
= GetStyle(item
);
731 if (def
&& GetRichTextCtrl())
733 GetRichTextCtrl()->ApplyStyle(def
);
734 GetRichTextCtrl()->SetFocus();
740 * wxRichTextStyleListCtrl class: manages a listbox and a choice control to
741 * switch shown style types
744 IMPLEMENT_CLASS(wxRichTextStyleListCtrl
, wxControl
)
746 BEGIN_EVENT_TABLE(wxRichTextStyleListCtrl
, wxControl
)
747 EVT_CHOICE(wxID_ANY
, wxRichTextStyleListCtrl::OnChooseType
)
748 EVT_SIZE(wxRichTextStyleListCtrl::OnSize
)
751 wxRichTextStyleListCtrl::wxRichTextStyleListCtrl(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
752 const wxSize
& size
, long style
)
755 Create(parent
, id
, pos
, size
, style
);
758 bool wxRichTextStyleListCtrl::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
759 const wxSize
& size
, long style
)
761 wxControl::Create(parent
, id
, pos
, size
, style
);
763 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
));
764 if (size
!= wxDefaultSize
)
765 SetInitialSize(size
);
767 bool showSelector
= ((style
& wxRICHTEXTSTYLELIST_HIDE_TYPE_SELECTOR
) == 0);
769 m_styleListBox
= new wxRichTextStyleListBox(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, showSelector
? wxSIMPLE_BORDER
: wxNO_BORDER
);
771 wxBoxSizer
* boxSizer
= new wxBoxSizer(wxVERTICAL
);
775 wxArrayString choices
;
776 choices
.Add(_("All styles"));
777 choices
.Add(_("Paragraph styles"));
778 choices
.Add(_("Character styles"));
779 choices
.Add(_("List styles"));
781 m_styleChoice
= new wxChoice(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, choices
);
783 boxSizer
->Add(m_styleListBox
, 1, wxALL
|wxEXPAND
, 5);
784 boxSizer
->Add(m_styleChoice
, 0, wxALL
|wxEXPAND
, 5);
788 boxSizer
->Add(m_styleListBox
, 1, wxALL
|wxEXPAND
, 0);
798 int i
= StyleTypeToIndex(m_styleListBox
->GetStyleType());
799 m_styleChoice
->SetSelection(i
);
802 m_dontUpdate
= false;
807 wxRichTextStyleListCtrl::~wxRichTextStyleListCtrl()
812 /// React to style type choice
813 void wxRichTextStyleListCtrl::OnChooseType(wxCommandEvent
& event
)
815 if (event
.GetEventObject() != m_styleChoice
)
822 wxRichTextStyleListBox::wxRichTextStyleType styleType
= StyleIndexToType(event
.GetSelection());
823 m_styleListBox
->SetStyleType(styleType
);
827 /// Lay out the controls
828 void wxRichTextStyleListCtrl::OnSize(wxSizeEvent
& WXUNUSED(event
))
834 /// Get the choice index for style type
835 int wxRichTextStyleListCtrl::StyleTypeToIndex(wxRichTextStyleListBox::wxRichTextStyleType styleType
)
837 if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
)
841 else if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH
)
845 else if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER
)
849 else if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST
)
856 /// Get the style type for choice index
857 wxRichTextStyleListBox::wxRichTextStyleType
wxRichTextStyleListCtrl::StyleIndexToType(int i
)
860 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH
;
862 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER
;
864 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST
;
866 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
;
869 /// Associates the control with a style manager
870 void wxRichTextStyleListCtrl::SetStyleSheet(wxRichTextStyleSheet
* styleSheet
)
873 m_styleListBox
->SetStyleSheet(styleSheet
);
876 wxRichTextStyleSheet
* wxRichTextStyleListCtrl::GetStyleSheet() const
879 return m_styleListBox
->GetStyleSheet();
884 /// Associates the control with a wxRichTextCtrl
885 void wxRichTextStyleListCtrl::SetRichTextCtrl(wxRichTextCtrl
* ctrl
)
888 m_styleListBox
->SetRichTextCtrl(ctrl
);
891 wxRichTextCtrl
* wxRichTextStyleListCtrl::GetRichTextCtrl() const
894 return m_styleListBox
->GetRichTextCtrl();
899 /// Set/get the style type to display
900 void wxRichTextStyleListCtrl::SetStyleType(wxRichTextStyleListBox::wxRichTextStyleType styleType
)
903 m_styleListBox
->SetStyleType(styleType
);
909 int i
= StyleTypeToIndex(m_styleListBox
->GetStyleType());
910 m_styleChoice
->SetSelection(i
);
913 m_dontUpdate
= false;
916 wxRichTextStyleListBox::wxRichTextStyleType
wxRichTextStyleListCtrl::GetStyleType() const
919 return m_styleListBox
->GetStyleType();
921 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
;
924 /// Updates the style list box
925 void wxRichTextStyleListCtrl::UpdateStyles()
928 m_styleListBox
->UpdateStyles();
934 * Style drop-down for a wxComboCtrl
938 BEGIN_EVENT_TABLE(wxRichTextStyleComboPopup
, wxRichTextStyleListBox
)
939 EVT_MOTION(wxRichTextStyleComboPopup::OnMouseMove
)
940 EVT_LEFT_DOWN(wxRichTextStyleComboPopup::OnMouseClick
)
943 void wxRichTextStyleComboPopup::SetStringValue( const wxString
& s
)
945 m_value
= SetStyleSelection(s
);
948 wxString
wxRichTextStyleComboPopup::GetStringValue() const
953 wxRichTextStyleDefinition
* def
= GetStyle(sel
);
955 return def
->GetName();
957 return wxEmptyString
;
961 // Popup event handlers
964 // Mouse hot-tracking
965 void wxRichTextStyleComboPopup::OnMouseMove(wxMouseEvent
& event
)
967 // Move selection to cursor if it is inside the popup
969 int itemHere
= wxRichTextStyleListBox::HitTest(event
.GetPosition());
972 wxRichTextStyleListBox::SetSelection(itemHere
);
973 m_itemHere
= itemHere
;
978 // On mouse left, set the value and close the popup
979 void wxRichTextStyleComboPopup::OnMouseClick(wxMouseEvent
& WXUNUSED(event
))
982 m_value
= m_itemHere
;
984 // Ordering is important, so we don't dismiss this popup accidentally
985 // by setting the focus elsewhere e.g. in ApplyStyle
989 wxRichTextStyleListBox::ApplyStyle(m_itemHere
);
993 * wxRichTextStyleComboCtrl
994 * A combo for applying styles.
997 IMPLEMENT_CLASS(wxRichTextStyleComboCtrl
, wxComboCtrl
)
999 BEGIN_EVENT_TABLE(wxRichTextStyleComboCtrl
, wxComboCtrl
)
1000 EVT_IDLE(wxRichTextStyleComboCtrl::OnIdle
)
1003 bool wxRichTextStyleComboCtrl::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
1004 const wxSize
& size
, long style
)
1006 if (!wxComboCtrl::Create(parent
, id
, wxEmptyString
, pos
, size
, style
))
1009 SetPopupMaxHeight(400);
1011 m_stylePopup
= new wxRichTextStyleComboPopup
;
1013 SetPopupControl(m_stylePopup
);
1018 /// Auto-select from style under caret in idle time
1020 // TODO: must be able to show italic, bold, combinations
1021 // in style box. Do we have a concept of automatic, temporary
1022 // styles that are added whenever we wish to show a style
1023 // that doesn't exist already? E.g. "Bold, Italic, Underline".
1024 // Word seems to generate these things on the fly.
1025 // If there's a named style already, it uses e.g. Heading1 + Bold, Italic
1026 // If you unembolden text in a style that has bold, it uses the
1028 // TODO: order styles alphabetically. This means indexes can change,
1029 // so need a different way to specify selections, i.e. by name.
1031 void wxRichTextStyleComboCtrl::OnIdle(wxIdleEvent
& event
)
1033 if (GetRichTextCtrl() && !IsPopupShown() && m_stylePopup
&& wxWindow::FindFocus() != this)
1035 wxString styleName
= wxRichTextStyleListBox::GetStyleToShowInIdleTime(GetRichTextCtrl(), m_stylePopup
->GetStyleType());
1037 wxString currentValue
= GetValue();
1038 if (!styleName
.IsEmpty())
1040 // Don't do the selection if it's already set
1041 if (currentValue
== styleName
)
1044 SetValue(styleName
);
1046 else if (!currentValue
.IsEmpty())
1047 SetValue(wxEmptyString
);