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 
 540     wxString 
str(wxT("<table><tr>")); 
 542     if (def
->GetStyle().GetLeftIndent() > 0) 
 544         wxClientDC 
dc((wxWindow
*) this); 
 546         str 
<< wxT("<td width=") << (ConvertTenthsMMToPixels(dc
, def
->GetStyle().GetLeftIndent())/2) << wxT("></td>"); 
 549     str 
<< wxT("<td nowrap>"); 
 557     int stdFontSize 
= 12; 
 558     int thisFontSize 
= ((def
->GetStyle().GetFlags() & wxTEXT_ATTR_FONT_SIZE
) != 0) ? def
->GetStyle().GetFontSize() : stdFontSize
; 
 560     if (thisFontSize 
< stdFontSize
) 
 562     else if (thisFontSize 
> stdFontSize
) 
 567     str 
<< wxT(" size=") << size
; 
 569     if (!def
->GetStyle().GetFontFaceName().IsEmpty()) 
 570         str 
<< wxT(" face=\"") << def
->GetStyle().GetFontFaceName() << wxT("\""); 
 572     if (def
->GetStyle().GetTextColour().Ok()) 
 573         str 
<< wxT(" color=\"#") << ColourToHexString(def
->GetStyle().GetTextColour()) << wxT("\""); 
 577     bool hasBold 
= false; 
 578     bool hasItalic 
= false; 
 579     bool hasUnderline 
= false; 
 581     if (def
->GetStyle().GetFontWeight() == wxBOLD
) 
 583     if (def
->GetStyle().GetFontStyle() == wxITALIC
) 
 585     if (def
->GetStyle().GetFontUnderlined()) 
 595     str 
+= def
->GetName(); 
 604     str 
<< wxT("</font>"); 
 606     str 
+= wxT("</td></tr></table>"); 
 610 // Convert units in tends of a millimetre to device units 
 611 int wxRichTextStyleListBox::ConvertTenthsMMToPixels(wxDC
& dc
, int units
) const 
 613     int ppi 
= dc
.GetPPI().x
; 
 615     // There are ppi pixels in 254.1 "1/10 mm" 
 617     double pixels 
= ((double) units 
* (double)ppi
) / 254.1; 
 622 void wxRichTextStyleListBox::OnLeftDown(wxMouseEvent
& event
) 
 624     wxVListBox::OnLeftDown(event
); 
 626     int item 
= HitTest(event
.GetPosition()); 
 627     if (item 
!= wxNOT_FOUND 
&& GetApplyOnSelection()) 
 631 void wxRichTextStyleListBox::OnLeftDoubleClick(wxMouseEvent
& event
) 
 633     wxVListBox::OnLeftDown(event
); 
 635     int item 
= HitTest(event
.GetPosition()); 
 636     if (item 
!= wxNOT_FOUND 
&& !GetApplyOnSelection()) 
 640 /// Helper for listbox and combo control 
 641 wxString 
wxRichTextStyleListBox::GetStyleToShowInIdleTime(wxRichTextCtrl
* ctrl
, wxRichTextStyleType styleType
) 
 643     int adjustedCaretPos 
= ctrl
->GetAdjustedCaretPosition(ctrl
->GetCaretPosition()); 
 645     wxRichTextParagraph
* para 
= ctrl
->GetBuffer().GetParagraphAtPosition(adjustedCaretPos
); 
 646     wxRichTextObject
* obj 
= ctrl
->GetBuffer().GetLeafObjectAtPosition(adjustedCaretPos
); 
 650     // Take into account current default style just chosen by user 
 651     if (ctrl
->IsDefaultStyleShowing()) 
 653         if ((styleType 
== wxRICHTEXT_STYLE_ALL 
|| styleType 
== wxRICHTEXT_STYLE_CHARACTER
) && 
 654                           !ctrl
->GetDefaultStyleEx().GetCharacterStyleName().IsEmpty()) 
 655             styleName 
= ctrl
->GetDefaultStyleEx().GetCharacterStyleName(); 
 656         else if ((styleType 
== wxRICHTEXT_STYLE_ALL 
|| styleType 
== wxRICHTEXT_STYLE_PARAGRAPH
) && 
 657                           !ctrl
->GetDefaultStyleEx().GetParagraphStyleName().IsEmpty()) 
 658             styleName 
= ctrl
->GetDefaultStyleEx().GetParagraphStyleName(); 
 659         else if ((styleType 
== wxRICHTEXT_STYLE_ALL 
|| styleType 
== wxRICHTEXT_STYLE_LIST
) && 
 660                           !ctrl
->GetDefaultStyleEx().GetListStyleName().IsEmpty()) 
 661             styleName 
= ctrl
->GetDefaultStyleEx().GetListStyleName(); 
 663     else if (obj 
&& (styleType 
== wxRICHTEXT_STYLE_ALL 
|| styleType 
== wxRICHTEXT_STYLE_CHARACTER
) && 
 664              !obj
->GetAttributes().GetCharacterStyleName().IsEmpty()) 
 666         styleName 
= obj
->GetAttributes().GetCharacterStyleName(); 
 668     else if (para 
&& (styleType 
== wxRICHTEXT_STYLE_ALL 
|| styleType 
== wxRICHTEXT_STYLE_PARAGRAPH
) && 
 669              !para
->GetAttributes().GetParagraphStyleName().IsEmpty()) 
 671         styleName 
= para
->GetAttributes().GetParagraphStyleName(); 
 673     else if (para 
&& (styleType 
== wxRICHTEXT_STYLE_ALL 
|| styleType 
== wxRICHTEXT_STYLE_LIST
) && 
 674              !para
->GetAttributes().GetListStyleName().IsEmpty()) 
 676         styleName 
= para
->GetAttributes().GetListStyleName(); 
 682 /// Auto-select from style under caret in idle time 
 683 void wxRichTextStyleListBox::OnIdle(wxIdleEvent
& event
) 
 685     if (CanAutoSetSelection() && GetRichTextCtrl() && wxWindow::FindFocus() != this) 
 687         wxString styleName 
= GetStyleToShowInIdleTime(GetRichTextCtrl(), GetStyleType()); 
 689         int sel 
= GetSelection(); 
 690         if (!styleName
.IsEmpty()) 
 692             // Don't do the selection if it's already set 
 693             if (sel 
== GetIndexForStyle(styleName
)) 
 696             SetStyleSelection(styleName
); 
 705 void wxRichTextStyleListBox::ApplyStyle(int item
) 
 707     if ( item 
!= wxNOT_FOUND 
) 
 709         wxRichTextStyleDefinition
* def 
= GetStyle(item
); 
 710         if (def 
&& GetRichTextCtrl()) 
 712             GetRichTextCtrl()->ApplyStyle(def
); 
 713             GetRichTextCtrl()->SetFocus(); 
 719  * wxRichTextStyleListCtrl class: manages a listbox and a choice control to 
 720  * switch shown style types 
 723 IMPLEMENT_CLASS(wxRichTextStyleListCtrl
, wxControl
) 
 725 BEGIN_EVENT_TABLE(wxRichTextStyleListCtrl
, wxControl
) 
 726     EVT_CHOICE(wxID_ANY
, wxRichTextStyleListCtrl::OnChooseType
) 
 727     EVT_SIZE(wxRichTextStyleListCtrl::OnSize
) 
 730 wxRichTextStyleListCtrl::wxRichTextStyleListCtrl(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
, 
 731     const wxSize
& size
, long style
) 
 734     Create(parent
, id
, pos
, size
, style
); 
 737 bool wxRichTextStyleListCtrl::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
, 
 738         const wxSize
& size
, long style
) 
 740     wxControl::Create(parent
, id
, pos
, size
, style
); 
 742     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
)); 
 743     if (size 
!= wxDefaultSize
) 
 744         SetInitialSize(size
); 
 746     bool showSelector 
= ((style 
& wxRICHTEXTSTYLELIST_HIDE_TYPE_SELECTOR
) == 0); 
 748     m_styleListBox 
= new wxRichTextStyleListBox(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, showSelector 
? wxSIMPLE_BORDER 
: wxNO_BORDER
); 
 750     wxBoxSizer
* boxSizer 
= new wxBoxSizer(wxVERTICAL
); 
 754         wxArrayString choices
; 
 755         choices
.Add(_("All styles")); 
 756         choices
.Add(_("Paragraph styles")); 
 757         choices
.Add(_("Character styles")); 
 758         choices
.Add(_("List styles")); 
 760         m_styleChoice 
= new wxChoice(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, choices
); 
 762         boxSizer
->Add(m_styleListBox
, 1, wxALL
|wxEXPAND
, 5); 
 763         boxSizer
->Add(m_styleChoice
, 0, wxALL
|wxEXPAND
, 5); 
 767         boxSizer
->Add(m_styleListBox
, 1, wxALL
|wxEXPAND
, 0); 
 777         int i 
= StyleTypeToIndex(m_styleListBox
->GetStyleType()); 
 778         m_styleChoice
->SetSelection(i
); 
 781     m_dontUpdate 
= false; 
 786 wxRichTextStyleListCtrl::~wxRichTextStyleListCtrl() 
 791 /// React to style type choice 
 792 void wxRichTextStyleListCtrl::OnChooseType(wxCommandEvent
& event
) 
 794     if (event
.GetEventObject() != m_styleChoice
) 
 801         wxRichTextStyleListBox::wxRichTextStyleType styleType 
= StyleIndexToType(event
.GetSelection()); 
 802         m_styleListBox
->SetStyleType(styleType
); 
 806 /// Lay out the controls 
 807 void wxRichTextStyleListCtrl::OnSize(wxSizeEvent
& WXUNUSED(event
)) 
 813 /// Get the choice index for style type 
 814 int wxRichTextStyleListCtrl::StyleTypeToIndex(wxRichTextStyleListBox::wxRichTextStyleType styleType
) 
 816     if (styleType 
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
) 
 820     else if (styleType 
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH
) 
 824     else if (styleType 
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER
) 
 828     else if (styleType 
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST
) 
 835 /// Get the style type for choice index 
 836 wxRichTextStyleListBox::wxRichTextStyleType 
wxRichTextStyleListCtrl::StyleIndexToType(int i
) 
 839         return wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH
; 
 841         return wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER
; 
 843         return wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST
; 
 845     return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
; 
 848 /// Associates the control with a style manager 
 849 void wxRichTextStyleListCtrl::SetStyleSheet(wxRichTextStyleSheet
* styleSheet
) 
 852         m_styleListBox
->SetStyleSheet(styleSheet
); 
 855 wxRichTextStyleSheet
* wxRichTextStyleListCtrl::GetStyleSheet() const 
 858         return m_styleListBox
->GetStyleSheet(); 
 863 /// Associates the control with a wxRichTextCtrl 
 864 void wxRichTextStyleListCtrl::SetRichTextCtrl(wxRichTextCtrl
* ctrl
) 
 867         m_styleListBox
->SetRichTextCtrl(ctrl
); 
 870 wxRichTextCtrl
* wxRichTextStyleListCtrl::GetRichTextCtrl() const 
 873         return m_styleListBox
->GetRichTextCtrl(); 
 878 /// Set/get the style type to display 
 879 void wxRichTextStyleListCtrl::SetStyleType(wxRichTextStyleListBox::wxRichTextStyleType styleType
) 
 882         m_styleListBox
->SetStyleType(styleType
); 
 888         int i 
= StyleTypeToIndex(m_styleListBox
->GetStyleType()); 
 889         m_styleChoice
->SetSelection(i
); 
 892     m_dontUpdate 
= false; 
 895 wxRichTextStyleListBox::wxRichTextStyleType 
wxRichTextStyleListCtrl::GetStyleType() const 
 898         return m_styleListBox
->GetStyleType(); 
 900         return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
; 
 903 /// Updates the style list box 
 904 void wxRichTextStyleListCtrl::UpdateStyles() 
 907         m_styleListBox
->UpdateStyles(); 
 913  * Style drop-down for a wxComboCtrl 
 917 BEGIN_EVENT_TABLE(wxRichTextStyleComboPopup
, wxRichTextStyleListBox
) 
 918     EVT_MOTION(wxRichTextStyleComboPopup::OnMouseMove
) 
 919     EVT_LEFT_DOWN(wxRichTextStyleComboPopup::OnMouseClick
) 
 922 void wxRichTextStyleComboPopup::SetStringValue( const wxString
& s 
) 
 924     m_value 
= SetStyleSelection(s
); 
 927 wxString 
wxRichTextStyleComboPopup::GetStringValue() const 
 932         wxRichTextStyleDefinition
* def 
= GetStyle(sel
); 
 934             return def
->GetName(); 
 936     return wxEmptyString
; 
 940 // Popup event handlers 
 943 // Mouse hot-tracking 
 944 void wxRichTextStyleComboPopup::OnMouseMove(wxMouseEvent
& event
) 
 946     // Move selection to cursor if it is inside the popup 
 948     int itemHere 
= wxRichTextStyleListBox::HitTest(event
.GetPosition()); 
 951         wxRichTextStyleListBox::SetSelection(itemHere
); 
 952         m_itemHere 
= itemHere
; 
 957 // On mouse left, set the value and close the popup 
 958 void wxRichTextStyleComboPopup::OnMouseClick(wxMouseEvent
& WXUNUSED(event
)) 
 961         m_value 
= m_itemHere
; 
 963     // Ordering is important, so we don't dismiss this popup accidentally 
 964     // by setting the focus elsewhere e.g. in ApplyStyle 
 968         wxRichTextStyleListBox::ApplyStyle(m_itemHere
); 
 972  * wxRichTextStyleComboCtrl 
 973  * A combo for applying styles. 
 976 IMPLEMENT_CLASS(wxRichTextStyleComboCtrl
, wxComboCtrl
) 
 978 BEGIN_EVENT_TABLE(wxRichTextStyleComboCtrl
, wxComboCtrl
) 
 979     EVT_IDLE(wxRichTextStyleComboCtrl::OnIdle
) 
 982 bool wxRichTextStyleComboCtrl::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
, 
 983         const wxSize
& size
, long style
) 
 985     if (!wxComboCtrl::Create(parent
, id
, wxEmptyString
, pos
, size
, style
)) 
 988     SetPopupMaxHeight(400); 
 990     m_stylePopup 
= new wxRichTextStyleComboPopup
; 
 992     SetPopupControl(m_stylePopup
); 
 997 /// Auto-select from style under caret in idle time 
 999 // TODO: must be able to show italic, bold, combinations 
1000 // in style box. Do we have a concept of automatic, temporary 
1001 // styles that are added whenever we wish to show a style 
1002 // that doesn't exist already? E.g. "Bold, Italic, Underline". 
1003 // Word seems to generate these things on the fly. 
1004 // If there's a named style already, it uses e.g. Heading1 + Bold, Italic 
1005 // If you unembolden text in a style that has bold, it uses the 
1007 // TODO: order styles alphabetically. This means indexes can change, 
1008 // so need a different way to specify selections, i.e. by name. 
1010 void wxRichTextStyleComboCtrl::OnIdle(wxIdleEvent
& event
) 
1012     if (GetRichTextCtrl() && !IsPopupShown() && m_stylePopup 
&& wxWindow::FindFocus() != this) 
1014         wxString styleName 
= wxRichTextStyleListBox::GetStyleToShowInIdleTime(GetRichTextCtrl(), m_stylePopup
->GetStyleType()); 
1016         wxString currentValue 
= GetValue(); 
1017         if (!styleName
.IsEmpty()) 
1019             // Don't do the selection if it's already set 
1020             if (currentValue 
== styleName
) 
1023             SetValue(styleName
); 
1025         else if (!currentValue
.IsEmpty()) 
1026             SetValue(wxEmptyString
);