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 wxRichTextAttr 
wxRichTextStyleDefinition::GetStyleMergedWithBase(const wxRichTextStyleSheet
* sheet
) const 
  59     if (!m_baseStyle
.IsEmpty()) 
  61         wxRichTextStyleDefinition
* baseStyle 
= sheet
->FindStyle(m_baseStyle
); 
  64             wxRichTextAttr 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 wxRichTextAttr
& attr
) 
 116     wxASSERT( (i 
>= 0 && i 
< 10) ); 
 117     if (i 
>= 0 && i 
< 10) 
 118         m_levelStyles
[i
] = attr
; 
 121 const wxRichTextAttr
* wxRichTextListStyleDefinition::GetLevelAttributes(int i
) const 
 123     wxASSERT( (i 
>= 0 && i 
< 10) ); 
 124     if (i 
>= 0 && i 
< 10) 
 125         return & m_levelStyles
[i
]; 
 130 wxRichTextAttr
* 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 wxRichTextAttr 
wxRichTextListStyleDefinition::CombineWithParagraphStyle(int indent
, const wxRichTextAttr
& paraStyle
, wxRichTextStyleSheet
* styleSheet
) 
 183     int listLevel 
= FindLevelForIndent(indent
); 
 185     wxRichTextAttr 
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 wxRichTextAttr 
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 wxRichTextAttr 
wxRichTextListStyleDefinition::GetCombinedStyleForLevel(int listLevel
, wxRichTextStyleSheet
* styleSheet
) 
 216     wxRichTextAttr 
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     wxRichTextAttr 
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()); 
 717     wxRichTextParagraph
* para 
= ctrl
->GetBuffer().GetParagraphAtPosition(adjustedCaretPos
); 
 718     wxRichTextObject
* obj 
= ctrl
->GetBuffer().GetLeafObjectAtPosition(adjustedCaretPos
); 
 722     // Take into account current default style just chosen by user 
 723     if (ctrl
->IsDefaultStyleShowing()) 
 727         ctrl
->GetStyle(adjustedCaretPos
, attr
); 
 728         wxRichTextApplyStyle(attr
, ctrl
->GetDefaultStyleEx()); 
 730         if ((styleType 
== wxRICHTEXT_STYLE_ALL 
|| styleType 
== wxRICHTEXT_STYLE_CHARACTER
) && 
 731                           !attr
.GetCharacterStyleName().IsEmpty()) 
 732             styleName 
= attr
.GetCharacterStyleName(); 
 733         else if ((styleType 
== wxRICHTEXT_STYLE_ALL 
|| styleType 
== wxRICHTEXT_STYLE_PARAGRAPH
) && 
 734                           !attr
.GetParagraphStyleName().IsEmpty()) 
 735             styleName 
= attr
.GetParagraphStyleName(); 
 736         else if ((styleType 
== wxRICHTEXT_STYLE_ALL 
|| styleType 
== wxRICHTEXT_STYLE_LIST
) && 
 737                           !attr
.GetListStyleName().IsEmpty()) 
 738             styleName 
= attr
.GetListStyleName(); 
 740     else if (obj 
&& (styleType 
== wxRICHTEXT_STYLE_ALL 
|| styleType 
== wxRICHTEXT_STYLE_CHARACTER
) && 
 741              !obj
->GetAttributes().GetCharacterStyleName().IsEmpty()) 
 743         styleName 
= obj
->GetAttributes().GetCharacterStyleName(); 
 745     else if (para 
&& (styleType 
== wxRICHTEXT_STYLE_ALL 
|| styleType 
== wxRICHTEXT_STYLE_PARAGRAPH
) && 
 746              !para
->GetAttributes().GetParagraphStyleName().IsEmpty()) 
 748         styleName 
= para
->GetAttributes().GetParagraphStyleName(); 
 750     else if (para 
&& (styleType 
== wxRICHTEXT_STYLE_ALL 
|| styleType 
== wxRICHTEXT_STYLE_LIST
) && 
 751              !para
->GetAttributes().GetListStyleName().IsEmpty()) 
 753         styleName 
= para
->GetAttributes().GetListStyleName(); 
 759 /// Auto-select from style under caret in idle time 
 760 void wxRichTextStyleListBox::OnIdle(wxIdleEvent
& event
) 
 762     if (CanAutoSetSelection() && GetRichTextCtrl() && wxWindow::FindFocus() != this) 
 764         wxString styleName 
= GetStyleToShowInIdleTime(GetRichTextCtrl(), GetStyleType()); 
 766         int sel 
= GetSelection(); 
 767         if (!styleName
.IsEmpty()) 
 769             // Don't do the selection if it's already set 
 770             if (sel 
== GetIndexForStyle(styleName
)) 
 773             SetStyleSelection(styleName
); 
 782 void wxRichTextStyleListBox::ApplyStyle(int item
) 
 784     if ( item 
!= wxNOT_FOUND 
) 
 786         wxRichTextStyleDefinition
* def 
= GetStyle(item
); 
 787         if (def 
&& GetRichTextCtrl()) 
 789             GetRichTextCtrl()->ApplyStyle(def
); 
 790             GetRichTextCtrl()->SetFocus(); 
 796  * wxRichTextStyleListCtrl class: manages a listbox and a choice control to 
 797  * switch shown style types 
 800 IMPLEMENT_CLASS(wxRichTextStyleListCtrl
, wxControl
) 
 802 BEGIN_EVENT_TABLE(wxRichTextStyleListCtrl
, wxControl
) 
 803     EVT_CHOICE(wxID_ANY
, wxRichTextStyleListCtrl::OnChooseType
) 
 804     EVT_SIZE(wxRichTextStyleListCtrl::OnSize
) 
 807 wxRichTextStyleListCtrl::wxRichTextStyleListCtrl(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
, 
 808     const wxSize
& size
, long style
) 
 811     Create(parent
, id
, pos
, size
, style
); 
 814 bool wxRichTextStyleListCtrl::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
, 
 815         const wxSize
& size
, long style
) 
 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     m_styleListBox 
= new wxRichTextStyleListBox(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, showSelector 
? wxSIMPLE_BORDER 
: wxNO_BORDER
); 
 827     wxBoxSizer
* boxSizer 
= new wxBoxSizer(wxVERTICAL
); 
 831         wxArrayString choices
; 
 832         choices
.Add(_("All styles")); 
 833         choices
.Add(_("Paragraph styles")); 
 834         choices
.Add(_("Character styles")); 
 835         choices
.Add(_("List styles")); 
 837         m_styleChoice 
= new wxChoice(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, choices
); 
 839         boxSizer
->Add(m_styleListBox
, 1, wxALL
|wxEXPAND
, 5); 
 840         boxSizer
->Add(m_styleChoice
, 0, wxALL
|wxEXPAND
, 5); 
 844         boxSizer
->Add(m_styleListBox
, 1, wxALL
|wxEXPAND
, 0); 
 854         int i 
= StyleTypeToIndex(m_styleListBox
->GetStyleType()); 
 855         m_styleChoice
->SetSelection(i
); 
 858     m_dontUpdate 
= false; 
 863 wxRichTextStyleListCtrl::~wxRichTextStyleListCtrl() 
 868 /// React to style type choice 
 869 void wxRichTextStyleListCtrl::OnChooseType(wxCommandEvent
& event
) 
 871     if (event
.GetEventObject() != m_styleChoice
) 
 878         wxRichTextStyleListBox::wxRichTextStyleType styleType 
= StyleIndexToType(event
.GetSelection()); 
 879         m_styleListBox
->SetStyleType(styleType
); 
 883 /// Lay out the controls 
 884 void wxRichTextStyleListCtrl::OnSize(wxSizeEvent
& WXUNUSED(event
)) 
 890 /// Get the choice index for style type 
 891 int wxRichTextStyleListCtrl::StyleTypeToIndex(wxRichTextStyleListBox::wxRichTextStyleType styleType
) 
 893     if (styleType 
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
) 
 897     else if (styleType 
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH
) 
 901     else if (styleType 
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER
) 
 905     else if (styleType 
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST
) 
 912 /// Get the style type for choice index 
 913 wxRichTextStyleListBox::wxRichTextStyleType 
wxRichTextStyleListCtrl::StyleIndexToType(int i
) 
 916         return wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH
; 
 918         return wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER
; 
 920         return wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST
; 
 922     return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
; 
 925 /// Associates the control with a style manager 
 926 void wxRichTextStyleListCtrl::SetStyleSheet(wxRichTextStyleSheet
* styleSheet
) 
 929         m_styleListBox
->SetStyleSheet(styleSheet
); 
 932 wxRichTextStyleSheet
* wxRichTextStyleListCtrl::GetStyleSheet() const 
 935         return m_styleListBox
->GetStyleSheet(); 
 940 /// Associates the control with a wxRichTextCtrl 
 941 void wxRichTextStyleListCtrl::SetRichTextCtrl(wxRichTextCtrl
* ctrl
) 
 944         m_styleListBox
->SetRichTextCtrl(ctrl
); 
 947 wxRichTextCtrl
* wxRichTextStyleListCtrl::GetRichTextCtrl() const 
 950         return m_styleListBox
->GetRichTextCtrl(); 
 955 /// Set/get the style type to display 
 956 void wxRichTextStyleListCtrl::SetStyleType(wxRichTextStyleListBox::wxRichTextStyleType styleType
) 
 958     if ( !m_styleListBox 
) 
 961     m_styleListBox
->SetStyleType(styleType
); 
 967         int i 
= StyleTypeToIndex(m_styleListBox
->GetStyleType()); 
 968         m_styleChoice
->SetSelection(i
); 
 971     m_dontUpdate 
= false; 
 974 wxRichTextStyleListBox::wxRichTextStyleType 
wxRichTextStyleListCtrl::GetStyleType() const 
 977         return m_styleListBox
->GetStyleType(); 
 979         return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
; 
 982 /// Updates the style list box 
 983 void wxRichTextStyleListCtrl::UpdateStyles() 
 986         m_styleListBox
->UpdateStyles(); 
 992  * Style drop-down for a wxComboCtrl 
 996 BEGIN_EVENT_TABLE(wxRichTextStyleComboPopup
, wxRichTextStyleListBox
) 
 997     EVT_MOTION(wxRichTextStyleComboPopup::OnMouseMove
) 
 998     EVT_LEFT_DOWN(wxRichTextStyleComboPopup::OnMouseClick
) 
1001 void wxRichTextStyleComboPopup::SetStringValue( const wxString
& s 
) 
1003     m_value 
= SetStyleSelection(s
); 
1006 wxString 
wxRichTextStyleComboPopup::GetStringValue() const 
1011         wxRichTextStyleDefinition
* def 
= GetStyle(sel
); 
1013             return def
->GetName(); 
1015     return wxEmptyString
; 
1019 // Popup event handlers 
1022 // Mouse hot-tracking 
1023 void wxRichTextStyleComboPopup::OnMouseMove(wxMouseEvent
& event
) 
1025     // Move selection to cursor if it is inside the popup 
1027     int itemHere 
= wxRichTextStyleListBox::HitTest(event
.GetPosition()); 
1028     if ( itemHere 
>= 0 ) 
1030         wxRichTextStyleListBox::SetSelection(itemHere
); 
1031         m_itemHere 
= itemHere
; 
1036 // On mouse left, set the value and close the popup 
1037 void wxRichTextStyleComboPopup::OnMouseClick(wxMouseEvent
& WXUNUSED(event
)) 
1039     if (m_itemHere 
>= 0) 
1040         m_value 
= m_itemHere
; 
1042     // Ordering is important, so we don't dismiss this popup accidentally 
1043     // by setting the focus elsewhere e.g. in ApplyStyle 
1046     if (m_itemHere 
>= 0) 
1047         wxRichTextStyleListBox::ApplyStyle(m_itemHere
); 
1051  * wxRichTextStyleComboCtrl 
1052  * A combo for applying styles. 
1055 IMPLEMENT_CLASS(wxRichTextStyleComboCtrl
, wxComboCtrl
) 
1057 BEGIN_EVENT_TABLE(wxRichTextStyleComboCtrl
, wxComboCtrl
) 
1058     EVT_IDLE(wxRichTextStyleComboCtrl::OnIdle
) 
1061 bool wxRichTextStyleComboCtrl::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
, 
1062         const wxSize
& size
, long style
) 
1064     if (!wxComboCtrl::Create(parent
, id
, wxEmptyString
, pos
, size
, style
)) 
1067     SetPopupMaxHeight(400); 
1069     m_stylePopup 
= new wxRichTextStyleComboPopup
; 
1071     SetPopupControl(m_stylePopup
); 
1076 /// Auto-select from style under caret in idle time 
1078 // TODO: must be able to show italic, bold, combinations 
1079 // in style box. Do we have a concept of automatic, temporary 
1080 // styles that are added whenever we wish to show a style 
1081 // that doesn't exist already? E.g. "Bold, Italic, Underline". 
1082 // Word seems to generate these things on the fly. 
1083 // If there's a named style already, it uses e.g. Heading1 + Bold, Italic 
1084 // If you unembolden text in a style that has bold, it uses the 
1086 // TODO: order styles alphabetically. This means indexes can change, 
1087 // so need a different way to specify selections, i.e. by name. 
1089 void wxRichTextStyleComboCtrl::OnIdle(wxIdleEvent
& event
) 
1091     if (GetRichTextCtrl() && !IsPopupShown() && m_stylePopup 
&& wxWindow::FindFocus() != this) 
1093         wxString styleName 
= wxRichTextStyleListBox::GetStyleToShowInIdleTime(GetRichTextCtrl(), m_stylePopup
->GetStyleType()); 
1095         wxString currentValue 
= GetValue(); 
1096         if (!styleName
.IsEmpty()) 
1098             // Don't do the selection if it's already set 
1099             if (currentValue 
== styleName
) 
1102             SetValue(styleName
); 
1104         else if (!currentValue
.IsEmpty()) 
1105             SetValue(wxEmptyString
);