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
;
50 bool wxRichTextStyleDefinition::Eq(const wxRichTextStyleDefinition
& def
) const
52 return (m_name
== def
.m_name
&& m_baseStyle
== def
.m_baseStyle
&& m_style
== def
.m_style
);
56 * Paragraph style definition
59 void wxRichTextParagraphStyleDefinition::Copy(const wxRichTextParagraphStyleDefinition
& def
)
61 wxRichTextStyleDefinition::Copy(def
);
63 m_nextStyle
= def
.m_nextStyle
;
66 bool wxRichTextParagraphStyleDefinition::operator ==(const wxRichTextParagraphStyleDefinition
& def
) const
68 return (Eq(def
) && m_nextStyle
== def
.m_nextStyle
);
72 * List style definition
75 void wxRichTextListStyleDefinition::Copy(const wxRichTextListStyleDefinition
& def
)
77 wxRichTextParagraphStyleDefinition::Copy(def
);
80 for (i
= 0; i
< 10; i
++)
81 m_levelStyles
[i
] = def
.m_levelStyles
[i
];
84 bool wxRichTextListStyleDefinition::operator ==(const wxRichTextListStyleDefinition
& def
) const
89 for (i
= 0; i
< 10; i
++)
90 if (!(m_levelStyles
[i
] == def
.m_levelStyles
[i
]))
96 /// Sets/gets the attributes for the given level
97 void wxRichTextListStyleDefinition::SetLevelAttributes(int i
, const wxTextAttrEx
& attr
)
99 wxASSERT( (i
>= 0 && i
< 10) );
100 if (i
>= 0 && i
< 10)
101 m_levelStyles
[i
] = attr
;
104 const wxTextAttrEx
* wxRichTextListStyleDefinition::GetLevelAttributes(int i
) const
106 wxASSERT( (i
>= 0 && i
< 10) );
107 if (i
>= 0 && i
< 10)
108 return & m_levelStyles
[i
];
113 wxTextAttrEx
* wxRichTextListStyleDefinition::GetLevelAttributes(int i
)
115 wxASSERT( (i
>= 0 && i
< 10) );
116 if (i
>= 0 && i
< 10)
117 return & m_levelStyles
[i
];
122 /// Convenience function for setting the major attributes for a list level specification
123 void wxRichTextListStyleDefinition::SetAttributes(int i
, int leftIndent
, int leftSubIndent
, int bulletStyle
, const wxString
& bulletSymbol
)
125 wxASSERT( (i
>= 0 && i
< 10) );
126 if (i
>= 0 && i
< 10)
130 attr
.SetBulletStyle(bulletStyle
);
131 attr
.SetLeftIndent(leftIndent
, leftSubIndent
);
133 if (!bulletSymbol
.IsEmpty())
134 attr
.SetBulletSymbol(bulletSymbol
[0]);
136 m_levelStyles
[i
] = attr
;
140 /// Finds the level corresponding to the given indentation
141 int wxRichTextListStyleDefinition::FindLevelForIndent(int indent
) const
144 for (i
= 0; i
< 10; i
++)
146 if (indent
< m_levelStyles
[i
].GetLeftIndent())
157 /// Combine the list style with a paragraph style, using the given indent (from which
158 /// an appropriate level is found)
159 wxTextAttrEx
wxRichTextListStyleDefinition::CombineWithParagraphStyle(int indent
, const wxTextAttrEx
& paraStyle
)
161 int listLevel
= FindLevelForIndent(indent
);
163 wxTextAttrEx
attr(*GetLevelAttributes(listLevel
));
164 int oldLeftIndent
= attr
.GetLeftIndent();
165 int oldLeftSubIndent
= attr
.GetLeftSubIndent();
167 // First apply the overall paragraph style, if any
168 wxRichTextApplyStyle(attr
, GetStyle());
170 // Then apply paragraph style, e.g. from paragraph style definition
171 wxRichTextApplyStyle(attr
, paraStyle
);
173 // We override the indents according to the list definition
174 attr
.SetLeftIndent(oldLeftIndent
, oldLeftSubIndent
);
179 /// Combine the base and list style, using the given indent (from which
180 /// an appropriate level is found)
181 wxTextAttrEx
wxRichTextListStyleDefinition::GetCombinedStyle(int indent
)
183 int listLevel
= FindLevelForIndent(indent
);
184 return GetCombinedStyleForLevel(listLevel
);
187 /// Combine the base and list style, using the given indent (from which
188 /// an appropriate level is found)
189 wxTextAttrEx
wxRichTextListStyleDefinition::GetCombinedStyleForLevel(int listLevel
)
191 wxTextAttrEx
attr(*GetLevelAttributes(listLevel
));
192 int oldLeftIndent
= attr
.GetLeftIndent();
193 int oldLeftSubIndent
= attr
.GetLeftSubIndent();
195 // Apply the overall paragraph style, if any
196 wxRichTextApplyStyle(attr
, GetStyle());
198 // We override the indents according to the list definition
199 attr
.SetLeftIndent(oldLeftIndent
, oldLeftSubIndent
);
204 /// Is this a numbered list?
205 bool wxRichTextListStyleDefinition::IsNumbered(int i
) const
207 return (0 != (GetLevelAttributes(i
)->GetFlags() &
208 (wxTEXT_ATTR_BULLET_STYLE_ARABIC
|wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER
|wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER
|
209 wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER
|wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER
)));
216 IMPLEMENT_CLASS(wxRichTextStyleSheet
, wxObject
)
218 wxRichTextStyleSheet::~wxRichTextStyleSheet()
223 m_nextSheet
->m_previousSheet
= m_previousSheet
;
226 m_previousSheet
->m_nextSheet
= m_nextSheet
;
228 m_previousSheet
= NULL
;
233 void wxRichTextStyleSheet::Init()
235 m_previousSheet
= NULL
;
239 /// Add a definition to one of the style lists
240 bool wxRichTextStyleSheet::AddStyle(wxList
& list
, wxRichTextStyleDefinition
* def
)
248 bool wxRichTextStyleSheet::RemoveStyle(wxList
& list
, wxRichTextStyleDefinition
* def
, bool deleteStyle
)
250 wxList::compatibility_iterator node
= list
.Find(def
);
253 wxRichTextStyleDefinition
* def
= (wxRichTextStyleDefinition
*) node
->GetData();
263 /// Find a definition by name
264 wxRichTextStyleDefinition
* wxRichTextStyleSheet::FindStyle(const wxList
& list
, const wxString
& name
, bool recurse
) const
266 for (wxList::compatibility_iterator node
= list
.GetFirst(); node
; node
= node
->GetNext())
268 wxRichTextStyleDefinition
* def
= (wxRichTextStyleDefinition
*) node
->GetData();
269 if (def
->GetName().Lower() == name
.Lower())
273 if (m_nextSheet
&& recurse
)
274 return m_nextSheet
->FindStyle(list
, name
, recurse
);
279 /// Delete all styles
280 void wxRichTextStyleSheet::DeleteStyles()
282 WX_CLEAR_LIST(wxList
, m_characterStyleDefinitions
);
283 WX_CLEAR_LIST(wxList
, m_paragraphStyleDefinitions
);
284 WX_CLEAR_LIST(wxList
, m_listStyleDefinitions
);
287 /// Insert into list of style sheets
288 bool wxRichTextStyleSheet::InsertSheet(wxRichTextStyleSheet
* before
)
290 m_previousSheet
= before
->m_previousSheet
;
291 m_nextSheet
= before
;
293 before
->m_previousSheet
= this;
297 /// Append to list of style sheets
298 bool wxRichTextStyleSheet::AppendSheet(wxRichTextStyleSheet
* after
)
300 wxRichTextStyleSheet
* last
= after
;
301 while (last
&& last
->m_nextSheet
)
303 last
= last
->m_nextSheet
;
308 m_previousSheet
= last
;
309 last
->m_nextSheet
= this;
317 /// Unlink from the list of style sheets
318 void wxRichTextStyleSheet::Unlink()
321 m_previousSheet
->m_nextSheet
= m_nextSheet
;
323 m_nextSheet
->m_previousSheet
= m_previousSheet
;
325 m_previousSheet
= NULL
;
329 /// Add a definition to the character style list
330 bool wxRichTextStyleSheet::AddCharacterStyle(wxRichTextCharacterStyleDefinition
* def
)
332 def
->GetStyle().SetCharacterStyleName(def
->GetName());
333 return AddStyle(m_characterStyleDefinitions
, def
);
336 /// Add a definition to the paragraph style list
337 bool wxRichTextStyleSheet::AddParagraphStyle(wxRichTextParagraphStyleDefinition
* def
)
339 def
->GetStyle().SetParagraphStyleName(def
->GetName());
340 return AddStyle(m_paragraphStyleDefinitions
, def
);
343 /// Add a definition to the list style list
344 bool wxRichTextStyleSheet::AddListStyle(wxRichTextListStyleDefinition
* def
)
346 def
->GetStyle().SetListStyleName(def
->GetName());
347 return AddStyle(m_listStyleDefinitions
, def
);
351 void wxRichTextStyleSheet::Copy(const wxRichTextStyleSheet
& sheet
)
355 wxList::compatibility_iterator node
;
357 for (node
= sheet
.m_characterStyleDefinitions
.GetFirst(); node
; node
= node
->GetNext())
359 wxRichTextCharacterStyleDefinition
* def
= (wxRichTextCharacterStyleDefinition
*) node
->GetData();
360 AddCharacterStyle(new wxRichTextCharacterStyleDefinition(*def
));
363 for (node
= sheet
.m_paragraphStyleDefinitions
.GetFirst(); node
; node
= node
->GetNext())
365 wxRichTextParagraphStyleDefinition
* def
= (wxRichTextParagraphStyleDefinition
*) node
->GetData();
366 AddParagraphStyle(new wxRichTextParagraphStyleDefinition(*def
));
369 for (node
= sheet
.m_listStyleDefinitions
.GetFirst(); node
; node
= node
->GetNext())
371 wxRichTextListStyleDefinition
* def
= (wxRichTextListStyleDefinition
*) node
->GetData();
372 AddListStyle(new wxRichTextListStyleDefinition(*def
));
377 bool wxRichTextStyleSheet::operator==(const wxRichTextStyleSheet
& WXUNUSED(sheet
)) const
386 * wxRichTextStyleListBox: a listbox to display styles.
389 IMPLEMENT_CLASS(wxRichTextStyleListBox
, wxHtmlListBox
)
391 BEGIN_EVENT_TABLE(wxRichTextStyleListBox
, wxHtmlListBox
)
392 EVT_LISTBOX(wxID_ANY
, wxRichTextStyleListBox::OnSelect
)
393 EVT_LEFT_DOWN(wxRichTextStyleListBox::OnLeftDown
)
394 EVT_LEFT_DCLICK(wxRichTextStyleListBox::OnLeftDoubleClick
)
395 EVT_IDLE(wxRichTextStyleListBox::OnIdle
)
398 wxRichTextStyleListBox::wxRichTextStyleListBox(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
399 const wxSize
& size
, long style
)
402 Create(parent
, id
, pos
, size
, style
);
405 bool wxRichTextStyleListBox::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
406 const wxSize
& size
, long style
)
408 return wxHtmlListBox::Create(parent
, id
, pos
, size
, style
);
411 wxRichTextStyleListBox::~wxRichTextStyleListBox()
415 /// Returns the HTML for this item
416 wxString
wxRichTextStyleListBox::OnGetItem(size_t n
) const
418 if (!GetStyleSheet())
419 return wxEmptyString
;
421 wxRichTextStyleDefinition
* def
= GetStyle(n
);
423 return CreateHTML(def
);
425 return wxEmptyString
;
428 // Get style for index
429 wxRichTextStyleDefinition
* wxRichTextStyleListBox::GetStyle(size_t i
) const
431 if (!GetStyleSheet())
434 if (GetStyleType() == wxRICHTEXT_STYLE_ALL
)
436 // First paragraph styles, then character, then list
437 if (i
< GetStyleSheet()->GetParagraphStyleCount())
438 return GetStyleSheet()->GetParagraphStyle(i
);
440 if ((i
- GetStyleSheet()->GetParagraphStyleCount()) < GetStyleSheet()->GetCharacterStyleCount())
441 return GetStyleSheet()->GetCharacterStyle(i
- GetStyleSheet()->GetParagraphStyleCount());
443 if ((i
- GetStyleSheet()->GetParagraphStyleCount() - GetStyleSheet()->GetCharacterStyleCount()) < GetStyleSheet()->GetListStyleCount())
444 return GetStyleSheet()->GetListStyle(i
- GetStyleSheet()->GetParagraphStyleCount() - GetStyleSheet()->GetCharacterStyleCount());
446 else if ((GetStyleType() == wxRICHTEXT_STYLE_PARAGRAPH
) && (i
< GetStyleSheet()->GetParagraphStyleCount()))
448 return GetStyleSheet()->GetParagraphStyle(i
);
450 else if ((GetStyleType() == wxRICHTEXT_STYLE_CHARACTER
) && (i
< GetStyleSheet()->GetCharacterStyleCount()))
452 return GetStyleSheet()->GetCharacterStyle(i
);
454 else if ((GetStyleType() == wxRICHTEXT_STYLE_LIST
) && (i
< GetStyleSheet()->GetListStyleCount()))
456 return GetStyleSheet()->GetListStyle(i
);
463 void wxRichTextStyleListBox::UpdateStyles()
467 if (GetStyleType() == wxRICHTEXT_STYLE_ALL
)
468 SetItemCount(GetStyleSheet()->GetParagraphStyleCount()+GetStyleSheet()->GetCharacterStyleCount()+GetStyleSheet()->GetListStyleCount());
469 else if (GetStyleType() == wxRICHTEXT_STYLE_PARAGRAPH
)
470 SetItemCount(GetStyleSheet()->GetParagraphStyleCount());
471 else if (GetStyleType() == wxRICHTEXT_STYLE_CHARACTER
)
472 SetItemCount(GetStyleSheet()->GetCharacterStyleCount());
473 else if (GetStyleType() == wxRICHTEXT_STYLE_LIST
)
474 SetItemCount(GetStyleSheet()->GetListStyleCount());
479 // Get index for style name
480 int wxRichTextStyleListBox::GetIndexForStyle(const wxString
& name
) const
484 int count
= GetItemCount();
487 for (i
= 0; i
< (int) count
; i
++)
489 wxRichTextStyleDefinition
* def
= GetStyle(i
);
490 if (def
->GetName() == name
)
497 /// Set selection for string
498 int wxRichTextStyleListBox::SetStyleSelection(const wxString
& name
)
500 int i
= GetIndexForStyle(name
);
506 // Convert a colour to a 6-digit hex string
507 static wxString
ColourToHexString(const wxColour
& col
)
511 hex
+= wxDecToHex(col
.Red());
512 hex
+= wxDecToHex(col
.Green());
513 hex
+= wxDecToHex(col
.Blue());
518 /// Creates a suitable HTML fragment for a definition
519 wxString
wxRichTextStyleListBox::CreateHTML(wxRichTextStyleDefinition
* def
) const
521 // TODO: indicate list format for list style types
523 wxString
str(wxT("<table><tr>"));
525 if (def
->GetStyle().GetLeftIndent() > 0)
527 wxClientDC
dc((wxWindow
*) this);
529 str
<< wxT("<td width=") << (ConvertTenthsMMToPixels(dc
, def
->GetStyle().GetLeftIndent())/2) << wxT("></td>");
532 str
<< wxT("<td nowrap>");
536 // Standard size is 12, say
537 size
+= (def
->GetStyle().HasFont() ? def
->GetStyle().GetFontSize() : 12) - 12;
541 str
<< wxT(" size=") << size
;
543 if (!def
->GetStyle().GetFontFaceName().IsEmpty())
544 str
<< wxT(" face=\"") << def
->GetStyle().GetFontFaceName() << wxT("\"");
546 if (def
->GetStyle().GetTextColour().Ok())
547 str
<< wxT(" color=\"#") << ColourToHexString(def
->GetStyle().GetTextColour()) << wxT("\"");
551 bool hasBold
= false;
552 bool hasItalic
= false;
553 bool hasUnderline
= false;
555 if (def
->GetStyle().GetFontWeight() == wxBOLD
)
557 if (def
->GetStyle().GetFontStyle() == wxITALIC
)
559 if (def
->GetStyle().GetFontUnderlined())
569 str
+= def
->GetName();
578 str
<< wxT("</font>");
580 str
+= wxT("</td></tr></table>");
584 // Convert units in tends of a millimetre to device units
585 int wxRichTextStyleListBox::ConvertTenthsMMToPixels(wxDC
& dc
, int units
) const
587 int ppi
= dc
.GetPPI().x
;
589 // There are ppi pixels in 254.1 "1/10 mm"
591 double pixels
= ((double) units
* (double)ppi
) / 254.1;
596 /// React to selection
597 void wxRichTextStyleListBox::OnSelect(wxCommandEvent
& WXUNUSED(event
))
600 wxRichTextStyleDefinition
* def
= GetStyle(event
.GetSelection());
603 wxMessageBox(def
->GetName());
608 void wxRichTextStyleListBox::OnLeftDown(wxMouseEvent
& event
)
610 wxVListBox::OnLeftDown(event
);
612 int item
= HitTest(event
.GetPosition());
613 if (item
!= wxNOT_FOUND
&& GetApplyOnSelection())
617 void wxRichTextStyleListBox::OnLeftDoubleClick(wxMouseEvent
& event
)
619 wxVListBox::OnLeftDown(event
);
621 int item
= HitTest(event
.GetPosition());
622 if (item
!= wxNOT_FOUND
&& !GetApplyOnSelection())
626 /// Helper for listbox and combo control
627 wxString
wxRichTextStyleListBox::GetStyleToShowInIdleTime(wxRichTextCtrl
* ctrl
, wxRichTextStyleType styleType
)
629 int adjustedCaretPos
= ctrl
->GetAdjustedCaretPosition(ctrl
->GetCaretPosition());
631 wxRichTextParagraph
* para
= ctrl
->GetBuffer().GetParagraphAtPosition(adjustedCaretPos
);
632 wxRichTextObject
* obj
= ctrl
->GetBuffer().GetLeafObjectAtPosition(adjustedCaretPos
);
636 // Take into account current default style just chosen by user
637 if (ctrl
->IsDefaultStyleShowing())
639 if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_CHARACTER
) &&
640 !ctrl
->GetDefaultStyleEx().GetCharacterStyleName().IsEmpty())
641 styleName
= ctrl
->GetDefaultStyleEx().GetCharacterStyleName();
642 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_PARAGRAPH
) &&
643 !ctrl
->GetDefaultStyleEx().GetParagraphStyleName().IsEmpty())
644 styleName
= ctrl
->GetDefaultStyleEx().GetParagraphStyleName();
645 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_LIST
) &&
646 !ctrl
->GetDefaultStyleEx().GetListStyleName().IsEmpty())
647 styleName
= ctrl
->GetDefaultStyleEx().GetListStyleName();
649 else if (obj
&& (styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_CHARACTER
) &&
650 !obj
->GetAttributes().GetCharacterStyleName().IsEmpty())
652 styleName
= obj
->GetAttributes().GetCharacterStyleName();
654 else if (para
&& (styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_PARAGRAPH
) &&
655 !para
->GetAttributes().GetParagraphStyleName().IsEmpty())
657 styleName
= para
->GetAttributes().GetParagraphStyleName();
659 else if (para
&& (styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_LIST
) &&
660 !para
->GetAttributes().GetListStyleName().IsEmpty())
662 styleName
= para
->GetAttributes().GetListStyleName();
668 /// Auto-select from style under caret in idle time
669 void wxRichTextStyleListBox::OnIdle(wxIdleEvent
& event
)
671 if (CanAutoSetSelection() && GetRichTextCtrl() && wxWindow::FindFocus() != this)
673 wxString styleName
= GetStyleToShowInIdleTime(GetRichTextCtrl(), GetStyleType());
675 int sel
= GetSelection();
676 if (!styleName
.IsEmpty())
678 // Don't do the selection if it's already set
679 if (sel
== GetIndexForStyle(styleName
))
682 SetStyleSelection(styleName
);
691 void wxRichTextStyleListBox::ApplyStyle(int item
)
693 if ( item
!= wxNOT_FOUND
)
695 wxRichTextStyleDefinition
* def
= GetStyle(item
);
696 if (def
&& GetRichTextCtrl())
698 GetRichTextCtrl()->ApplyStyle(def
);
699 GetRichTextCtrl()->SetFocus();
705 * wxRichTextStyleListCtrl class: manages a listbox and a choice control to
706 * switch shown style types
709 IMPLEMENT_CLASS(wxRichTextStyleListCtrl
, wxControl
)
711 BEGIN_EVENT_TABLE(wxRichTextStyleListCtrl
, wxControl
)
712 EVT_CHOICE(wxID_ANY
, wxRichTextStyleListCtrl::OnChooseType
)
713 EVT_SIZE(wxRichTextStyleListCtrl::OnSize
)
716 wxRichTextStyleListCtrl::wxRichTextStyleListCtrl(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
717 const wxSize
& size
, long style
)
720 Create(parent
, id
, pos
, size
, style
);
723 bool wxRichTextStyleListCtrl::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
724 const wxSize
& size
, long style
)
726 wxControl::Create(parent
, id
, pos
, size
, style
);
728 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
));
730 m_styleListBox
= new wxRichTextStyleListBox(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, wxSIMPLE_BORDER
);
732 wxArrayString choices
;
733 choices
.Add(_("All styles"));
734 choices
.Add(_("Paragraph styles"));
735 choices
.Add(_("Character styles"));
736 choices
.Add(_("List styles"));
738 m_styleChoice
= new wxChoice(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, choices
);
740 wxBoxSizer
* boxSizer
= new wxBoxSizer(wxVERTICAL
);
741 boxSizer
->Add(m_styleListBox
, 1, wxALL
|wxEXPAND
, 5);
742 boxSizer
->Add(m_styleChoice
, 0, wxALL
|wxEXPAND
, 5);
748 int i
= StyleTypeToIndex(m_styleListBox
->GetStyleType());
749 m_styleChoice
->SetSelection(i
);
751 m_dontUpdate
= false;
756 wxRichTextStyleListCtrl::~wxRichTextStyleListCtrl()
760 /// React to style type choice
761 void wxRichTextStyleListCtrl::OnChooseType(wxCommandEvent
& event
)
763 if (event
.GetEventObject() != m_styleChoice
)
770 wxRichTextStyleListBox::wxRichTextStyleType styleType
= StyleIndexToType(event
.GetSelection());
771 m_styleListBox
->SetStyleType(styleType
);
775 /// Lay out the controls
776 void wxRichTextStyleListCtrl::OnSize(wxSizeEvent
& WXUNUSED(event
))
782 /// Get the choice index for style type
783 int wxRichTextStyleListCtrl::StyleTypeToIndex(wxRichTextStyleListBox::wxRichTextStyleType styleType
)
785 if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
)
789 else if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH
)
793 else if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER
)
797 else if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST
)
804 /// Get the style type for choice index
805 wxRichTextStyleListBox::wxRichTextStyleType
wxRichTextStyleListCtrl::StyleIndexToType(int i
)
808 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH
;
810 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER
;
812 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST
;
814 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
;
817 /// Associates the control with a style manager
818 void wxRichTextStyleListCtrl::SetStyleSheet(wxRichTextStyleSheet
* styleSheet
)
821 m_styleListBox
->SetStyleSheet(styleSheet
);
824 wxRichTextStyleSheet
* wxRichTextStyleListCtrl::GetStyleSheet() const
827 return m_styleListBox
->GetStyleSheet();
832 /// Associates the control with a wxRichTextCtrl
833 void wxRichTextStyleListCtrl::SetRichTextCtrl(wxRichTextCtrl
* ctrl
)
836 m_styleListBox
->SetRichTextCtrl(ctrl
);
839 wxRichTextCtrl
* wxRichTextStyleListCtrl::GetRichTextCtrl() const
842 return m_styleListBox
->GetRichTextCtrl();
847 /// Set/get the style type to display
848 void wxRichTextStyleListCtrl::SetStyleType(wxRichTextStyleListBox::wxRichTextStyleType styleType
)
851 m_styleListBox
->SetStyleType(styleType
);
857 int i
= StyleTypeToIndex(m_styleListBox
->GetStyleType());
858 m_styleChoice
->SetSelection(i
);
861 m_dontUpdate
= false;
864 wxRichTextStyleListBox::wxRichTextStyleType
wxRichTextStyleListCtrl::GetStyleType() const
867 return m_styleListBox
->GetStyleType();
869 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
;
872 /// Updates the style list box
873 void wxRichTextStyleListCtrl::UpdateStyles()
876 m_styleListBox
->UpdateStyles();
882 * Style drop-down for a wxComboCtrl
886 BEGIN_EVENT_TABLE(wxRichTextStyleComboPopup
, wxRichTextStyleListBox
)
887 EVT_MOTION(wxRichTextStyleComboPopup::OnMouseMove
)
888 EVT_LEFT_DOWN(wxRichTextStyleComboPopup::OnMouseClick
)
891 void wxRichTextStyleComboPopup::SetStringValue( const wxString
& s
)
893 m_value
= SetStyleSelection(s
);
896 wxString
wxRichTextStyleComboPopup::GetStringValue() const
901 wxRichTextStyleDefinition
* def
= GetStyle(sel
);
903 return def
->GetName();
905 return wxEmptyString
;
909 // Popup event handlers
912 // Mouse hot-tracking
913 void wxRichTextStyleComboPopup::OnMouseMove(wxMouseEvent
& event
)
915 // Move selection to cursor if it is inside the popup
917 int itemHere
= wxRichTextStyleListBox::HitTest(event
.GetPosition());
920 wxRichTextStyleListBox::SetSelection(itemHere
);
921 m_itemHere
= itemHere
;
926 // On mouse left, set the value and close the popup
927 void wxRichTextStyleComboPopup::OnMouseClick(wxMouseEvent
& WXUNUSED(event
))
930 m_value
= m_itemHere
;
932 // Ordering is important, so we don't dismiss this popup accidentally
933 // by setting the focus elsewhere e.g. in ApplyStyle
937 wxRichTextStyleListBox::ApplyStyle(m_itemHere
);
941 * wxRichTextStyleComboCtrl
942 * A combo for applying styles.
945 IMPLEMENT_CLASS(wxRichTextStyleComboCtrl
, wxComboCtrl
)
947 BEGIN_EVENT_TABLE(wxRichTextStyleComboCtrl
, wxComboCtrl
)
948 EVT_IDLE(wxRichTextStyleComboCtrl::OnIdle
)
951 bool wxRichTextStyleComboCtrl::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
952 const wxSize
& size
, long style
)
954 if (!wxComboCtrl::Create(parent
, id
, wxEmptyString
, pos
, size
, style
))
957 SetPopupMaxHeight(400);
959 m_stylePopup
= new wxRichTextStyleComboPopup
;
961 SetPopupControl(m_stylePopup
);
966 /// Auto-select from style under caret in idle time
968 // TODO: must be able to show italic, bold, combinations
969 // in style box. Do we have a concept of automatic, temporary
970 // styles that are added whenever we wish to show a style
971 // that doesn't exist already? E.g. "Bold, Italic, Underline".
972 // Word seems to generate these things on the fly.
973 // If there's a named style already, it uses e.g. Heading1 + Bold, Italic
974 // If you unembolden text in a style that has bold, it uses the
976 // TODO: order styles alphabetically. This means indexes can change,
977 // so need a different way to specify selections, i.e. by name.
979 void wxRichTextStyleComboCtrl::OnIdle(wxIdleEvent
& event
)
981 if (GetRichTextCtrl() && !IsPopupShown() && m_stylePopup
&& wxWindow::FindFocus() != this)
983 wxString styleName
= wxRichTextStyleListBox::GetStyleToShowInIdleTime(GetRichTextCtrl(), m_stylePopup
->GetStyleType());
985 wxString currentValue
= GetValue();
986 if (!styleName
.IsEmpty())
988 // Don't do the selection if it's already set
989 if (currentValue
== styleName
)
994 else if (!currentValue
.IsEmpty())
995 SetValue(wxEmptyString
);