1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/richtext/richtextstyles.cpp
3 // Purpose: Style management for wxRichTextCtrl
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
21 #include "wx/richtext/richtextstyles.h"
27 #include "wx/filename.h"
28 #include "wx/clipbrd.h"
29 #include "wx/wfstream.h"
30 #include "wx/settings.h"
32 #include "wx/richtext/richtextctrl.h"
34 IMPLEMENT_CLASS(wxRichTextStyleDefinition
, wxObject
)
35 IMPLEMENT_CLASS(wxRichTextCharacterStyleDefinition
, wxRichTextStyleDefinition
)
36 IMPLEMENT_CLASS(wxRichTextParagraphStyleDefinition
, wxRichTextStyleDefinition
)
37 IMPLEMENT_CLASS(wxRichTextListStyleDefinition
, wxRichTextParagraphStyleDefinition
)
43 void wxRichTextStyleDefinition::Copy(const wxRichTextStyleDefinition
& def
)
46 m_baseStyle
= def
.m_baseStyle
;
47 m_style
= def
.m_style
;
48 m_description
= def
.m_description
;
51 bool wxRichTextStyleDefinition::Eq(const wxRichTextStyleDefinition
& def
) const
53 return (m_name
== def
.m_name
&& m_baseStyle
== def
.m_baseStyle
&& m_style
== def
.m_style
);
56 /// Gets the style combined with the base style
57 wxTextAttr
wxRichTextStyleDefinition::GetStyleMergedWithBase(const wxRichTextStyleSheet
* sheet
) const
59 if (!m_baseStyle
.IsEmpty())
61 wxRichTextStyleDefinition
* baseStyle
= sheet
->FindStyle(m_baseStyle
);
64 wxTextAttr baseAttr
= baseStyle
->GetStyleMergedWithBase(sheet
);
65 baseAttr
.Apply(m_style
, NULL
);
73 * Paragraph style definition
76 void wxRichTextParagraphStyleDefinition::Copy(const wxRichTextParagraphStyleDefinition
& def
)
78 wxRichTextStyleDefinition::Copy(def
);
80 m_nextStyle
= def
.m_nextStyle
;
83 bool wxRichTextParagraphStyleDefinition::operator ==(const wxRichTextParagraphStyleDefinition
& def
) const
85 return (Eq(def
) && m_nextStyle
== def
.m_nextStyle
);
89 * List style definition
92 void wxRichTextListStyleDefinition::Copy(const wxRichTextListStyleDefinition
& def
)
94 wxRichTextParagraphStyleDefinition::Copy(def
);
97 for (i
= 0; i
< 10; i
++)
98 m_levelStyles
[i
] = def
.m_levelStyles
[i
];
101 bool wxRichTextListStyleDefinition::operator ==(const wxRichTextListStyleDefinition
& def
) const
106 for (i
= 0; i
< 10; i
++)
107 if (!(m_levelStyles
[i
] == def
.m_levelStyles
[i
]))
113 /// Sets/gets the attributes for the given level
114 void wxRichTextListStyleDefinition::SetLevelAttributes(int i
, const wxTextAttr
& attr
)
116 wxASSERT( (i
>= 0 && i
< 10) );
117 if (i
>= 0 && i
< 10)
118 m_levelStyles
[i
] = attr
;
121 const wxTextAttr
* wxRichTextListStyleDefinition::GetLevelAttributes(int i
) const
123 wxASSERT( (i
>= 0 && i
< 10) );
124 if (i
>= 0 && i
< 10)
125 return & m_levelStyles
[i
];
130 wxTextAttr
* wxRichTextListStyleDefinition::GetLevelAttributes(int i
)
132 wxASSERT( (i
>= 0 && i
< 10) );
133 if (i
>= 0 && i
< 10)
134 return & m_levelStyles
[i
];
139 /// Convenience function for setting the major attributes for a list level specification
140 void wxRichTextListStyleDefinition::SetAttributes(int i
, int leftIndent
, int leftSubIndent
, int bulletStyle
, const wxString
& bulletSymbol
)
142 wxASSERT( (i
>= 0 && i
< 10) );
143 if (i
>= 0 && i
< 10)
147 attr
.SetBulletStyle(bulletStyle
);
148 attr
.SetLeftIndent(leftIndent
, leftSubIndent
);
150 if (!bulletSymbol
.IsEmpty())
152 if (bulletStyle
& wxTEXT_ATTR_BULLET_STYLE_SYMBOL
)
153 attr
.SetBulletText(bulletSymbol
);
155 attr
.SetBulletName(bulletSymbol
);
158 m_levelStyles
[i
] = attr
;
162 /// Finds the level corresponding to the given indentation
163 int wxRichTextListStyleDefinition::FindLevelForIndent(int indent
) const
166 for (i
= 0; i
< 10; i
++)
168 if (indent
< m_levelStyles
[i
].GetLeftIndent())
179 /// Combine the list style with a paragraph style, using the given indent (from which
180 /// an appropriate level is found)
181 wxTextAttr
wxRichTextListStyleDefinition::CombineWithParagraphStyle(int indent
, const wxTextAttr
& paraStyle
, wxRichTextStyleSheet
* styleSheet
)
183 int listLevel
= FindLevelForIndent(indent
);
185 wxTextAttr
attr(*GetLevelAttributes(listLevel
));
186 int oldLeftIndent
= attr
.GetLeftIndent();
187 int oldLeftSubIndent
= attr
.GetLeftSubIndent();
189 // First apply the overall paragraph style, if any
191 attr
.Apply(GetStyleMergedWithBase(styleSheet
));
193 attr
.Apply(GetStyle());
195 // Then apply paragraph style, e.g. from paragraph style definition
196 attr
.Apply(paraStyle
);
198 // We override the indents according to the list definition
199 attr
.SetLeftIndent(oldLeftIndent
, oldLeftSubIndent
);
204 /// Combine the base and list style, using the given indent (from which
205 /// an appropriate level is found)
206 wxTextAttr
wxRichTextListStyleDefinition::GetCombinedStyle(int indent
, wxRichTextStyleSheet
* styleSheet
)
208 int listLevel
= FindLevelForIndent(indent
);
209 return GetCombinedStyleForLevel(listLevel
, styleSheet
);
212 /// Combine the base and list style, using the given indent (from which
213 /// an appropriate level is found)
214 wxTextAttr
wxRichTextListStyleDefinition::GetCombinedStyleForLevel(int listLevel
, wxRichTextStyleSheet
* styleSheet
)
216 wxTextAttr
attr(*GetLevelAttributes(listLevel
));
217 int oldLeftIndent
= attr
.GetLeftIndent();
218 int oldLeftSubIndent
= attr
.GetLeftSubIndent();
220 // Apply the overall paragraph style, if any
222 attr
.Apply(GetStyleMergedWithBase(styleSheet
));
224 attr
.Apply(GetStyle());
226 // We override the indents according to the list definition
227 attr
.SetLeftIndent(oldLeftIndent
, oldLeftSubIndent
);
232 /// Is this a numbered list?
233 bool wxRichTextListStyleDefinition::IsNumbered(int i
) const
235 return (0 != (GetLevelAttributes(i
)->GetFlags() &
236 (wxTEXT_ATTR_BULLET_STYLE_ARABIC
|wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER
|wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER
|
237 wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER
|wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER
)));
244 IMPLEMENT_CLASS(wxRichTextStyleSheet
, wxObject
)
246 wxRichTextStyleSheet::~wxRichTextStyleSheet()
251 m_nextSheet
->m_previousSheet
= m_previousSheet
;
254 m_previousSheet
->m_nextSheet
= m_nextSheet
;
256 m_previousSheet
= NULL
;
261 void wxRichTextStyleSheet::Init()
263 m_previousSheet
= NULL
;
267 /// Add a definition to one of the style lists
268 bool wxRichTextStyleSheet::AddStyle(wxList
& list
, wxRichTextStyleDefinition
* def
)
276 bool wxRichTextStyleSheet::RemoveStyle(wxList
& list
, wxRichTextStyleDefinition
* def
, bool deleteStyle
)
278 wxList::compatibility_iterator node
= list
.Find(def
);
281 wxRichTextStyleDefinition
* def
= (wxRichTextStyleDefinition
*) node
->GetData();
292 bool wxRichTextStyleSheet::RemoveStyle(wxRichTextStyleDefinition
* def
, bool deleteStyle
)
294 if (RemoveParagraphStyle(def
, deleteStyle
))
296 if (RemoveCharacterStyle(def
, deleteStyle
))
298 if (RemoveListStyle(def
, deleteStyle
))
303 /// Find a definition by name
304 wxRichTextStyleDefinition
* wxRichTextStyleSheet::FindStyle(const wxList
& list
, const wxString
& name
, bool recurse
) const
306 for (wxList::compatibility_iterator node
= list
.GetFirst(); node
; node
= node
->GetNext())
308 wxRichTextStyleDefinition
* def
= (wxRichTextStyleDefinition
*) node
->GetData();
309 if (def
->GetName().Lower() == name
.Lower())
313 if (m_nextSheet
&& recurse
)
314 return m_nextSheet
->FindStyle(list
, name
, recurse
);
319 /// Delete all styles
320 void wxRichTextStyleSheet::DeleteStyles()
322 WX_CLEAR_LIST(wxList
, m_characterStyleDefinitions
);
323 WX_CLEAR_LIST(wxList
, m_paragraphStyleDefinitions
);
324 WX_CLEAR_LIST(wxList
, m_listStyleDefinitions
);
327 /// Insert into list of style sheets
328 bool wxRichTextStyleSheet::InsertSheet(wxRichTextStyleSheet
* before
)
330 m_previousSheet
= before
->m_previousSheet
;
331 m_nextSheet
= before
;
333 before
->m_previousSheet
= this;
337 /// Append to list of style sheets
338 bool wxRichTextStyleSheet::AppendSheet(wxRichTextStyleSheet
* after
)
340 wxRichTextStyleSheet
* last
= after
;
341 while (last
&& last
->m_nextSheet
)
343 last
= last
->m_nextSheet
;
348 m_previousSheet
= last
;
349 last
->m_nextSheet
= this;
357 /// Unlink from the list of style sheets
358 void wxRichTextStyleSheet::Unlink()
361 m_previousSheet
->m_nextSheet
= m_nextSheet
;
363 m_nextSheet
->m_previousSheet
= m_previousSheet
;
365 m_previousSheet
= NULL
;
369 /// Add a definition to the character style list
370 bool wxRichTextStyleSheet::AddCharacterStyle(wxRichTextCharacterStyleDefinition
* def
)
372 def
->GetStyle().SetCharacterStyleName(def
->GetName());
373 return AddStyle(m_characterStyleDefinitions
, def
);
376 /// Add a definition to the paragraph style list
377 bool wxRichTextStyleSheet::AddParagraphStyle(wxRichTextParagraphStyleDefinition
* def
)
379 def
->GetStyle().SetParagraphStyleName(def
->GetName());
380 return AddStyle(m_paragraphStyleDefinitions
, def
);
383 /// Add a definition to the list style list
384 bool wxRichTextStyleSheet::AddListStyle(wxRichTextListStyleDefinition
* def
)
386 def
->GetStyle().SetListStyleName(def
->GetName());
387 return AddStyle(m_listStyleDefinitions
, def
);
390 /// Add a definition to the appropriate style list
391 bool wxRichTextStyleSheet::AddStyle(wxRichTextStyleDefinition
* def
)
393 wxRichTextListStyleDefinition
* listDef
= wxDynamicCast(def
, wxRichTextListStyleDefinition
);
395 return AddListStyle(listDef
);
397 wxRichTextParagraphStyleDefinition
* paraDef
= wxDynamicCast(def
, wxRichTextParagraphStyleDefinition
);
399 return AddParagraphStyle(paraDef
);
401 wxRichTextCharacterStyleDefinition
* charDef
= wxDynamicCast(def
, wxRichTextCharacterStyleDefinition
);
403 return AddCharacterStyle(charDef
);
408 /// Find any definition by name
409 wxRichTextStyleDefinition
* wxRichTextStyleSheet::FindStyle(const wxString
& name
, bool recurse
) const
411 wxRichTextListStyleDefinition
* listDef
= FindListStyle(name
, recurse
);
415 wxRichTextParagraphStyleDefinition
* paraDef
= FindParagraphStyle(name
, recurse
);
419 wxRichTextCharacterStyleDefinition
* charDef
= FindCharacterStyle(name
, recurse
);
427 void wxRichTextStyleSheet::Copy(const wxRichTextStyleSheet
& sheet
)
431 wxList::compatibility_iterator node
;
433 for (node
= sheet
.m_characterStyleDefinitions
.GetFirst(); node
; node
= node
->GetNext())
435 wxRichTextCharacterStyleDefinition
* def
= (wxRichTextCharacterStyleDefinition
*) node
->GetData();
436 AddCharacterStyle(new wxRichTextCharacterStyleDefinition(*def
));
439 for (node
= sheet
.m_paragraphStyleDefinitions
.GetFirst(); node
; node
= node
->GetNext())
441 wxRichTextParagraphStyleDefinition
* def
= (wxRichTextParagraphStyleDefinition
*) node
->GetData();
442 AddParagraphStyle(new wxRichTextParagraphStyleDefinition(*def
));
445 for (node
= sheet
.m_listStyleDefinitions
.GetFirst(); node
; node
= node
->GetNext())
447 wxRichTextListStyleDefinition
* def
= (wxRichTextListStyleDefinition
*) node
->GetData();
448 AddListStyle(new wxRichTextListStyleDefinition(*def
));
451 SetName(sheet
.GetName());
452 SetDescription(sheet
.GetDescription());
456 bool wxRichTextStyleSheet::operator==(const wxRichTextStyleSheet
& WXUNUSED(sheet
)) const
465 * wxRichTextStyleListBox: a listbox to display styles.
468 IMPLEMENT_CLASS(wxRichTextStyleListBox
, wxHtmlListBox
)
470 BEGIN_EVENT_TABLE(wxRichTextStyleListBox
, wxHtmlListBox
)
471 EVT_LEFT_DOWN(wxRichTextStyleListBox::OnLeftDown
)
472 EVT_LEFT_DCLICK(wxRichTextStyleListBox::OnLeftDoubleClick
)
473 EVT_IDLE(wxRichTextStyleListBox::OnIdle
)
476 wxRichTextStyleListBox::wxRichTextStyleListBox(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
477 const wxSize
& size
, long style
)
480 Create(parent
, id
, pos
, size
, style
);
483 bool wxRichTextStyleListBox::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
484 const wxSize
& size
, long style
)
486 return wxHtmlListBox::Create(parent
, id
, pos
, size
, style
);
489 wxRichTextStyleListBox::~wxRichTextStyleListBox()
493 /// Returns the HTML for this item
494 wxString
wxRichTextStyleListBox::OnGetItem(size_t n
) const
496 if (!GetStyleSheet())
497 return wxEmptyString
;
499 wxRichTextStyleDefinition
* def
= GetStyle(n
);
501 return CreateHTML(def
);
503 return wxEmptyString
;
506 // Get style for index
507 wxRichTextStyleDefinition
* wxRichTextStyleListBox::GetStyle(size_t i
) const
509 if (!GetStyleSheet())
512 if (i
>= m_styleNames
.GetCount() /* || i < 0 */ )
515 return GetStyleSheet()->FindStyle(m_styleNames
[i
]);
519 void wxRichTextStyleListBox::UpdateStyles()
523 int oldSel
= GetSelection();
525 SetSelection(wxNOT_FOUND
);
527 m_styleNames
.Clear();
530 if (GetStyleType() == wxRICHTEXT_STYLE_ALL
|| GetStyleType() == wxRICHTEXT_STYLE_PARAGRAPH
)
532 for (i
= 0; i
< GetStyleSheet()->GetParagraphStyleCount(); i
++)
533 m_styleNames
.Add(GetStyleSheet()->GetParagraphStyle(i
)->GetName());
535 if (GetStyleType() == wxRICHTEXT_STYLE_ALL
|| GetStyleType() == wxRICHTEXT_STYLE_CHARACTER
)
537 for (i
= 0; i
< GetStyleSheet()->GetCharacterStyleCount(); i
++)
538 m_styleNames
.Add(GetStyleSheet()->GetCharacterStyle(i
)->GetName());
540 if (GetStyleType() == wxRICHTEXT_STYLE_ALL
|| GetStyleType() == wxRICHTEXT_STYLE_LIST
)
542 for (i
= 0; i
< GetStyleSheet()->GetListStyleCount(); i
++)
543 m_styleNames
.Add(GetStyleSheet()->GetListStyle(i
)->GetName());
547 SetItemCount(m_styleNames
.GetCount());
552 if (oldSel
>= 0 && oldSel
< (int) GetItemCount())
554 else if (GetItemCount() > 0)
559 SetSelection(newSel
);
565 // Get index for style name
566 int wxRichTextStyleListBox::GetIndexForStyle(const wxString
& name
) const
568 return m_styleNames
.Index(name
);
571 /// Set selection for string
572 int wxRichTextStyleListBox::SetStyleSelection(const wxString
& name
)
574 int i
= GetIndexForStyle(name
);
580 // Convert a colour to a 6-digit hex string
581 static wxString
ColourToHexString(const wxColour
& col
)
585 hex
+= wxDecToHex(col
.Red());
586 hex
+= wxDecToHex(col
.Green());
587 hex
+= wxDecToHex(col
.Blue());
592 /// Creates a suitable HTML fragment for a definition
593 wxString
wxRichTextStyleListBox::CreateHTML(wxRichTextStyleDefinition
* def
) const
595 // TODO: indicate list format for list style types
599 bool isCentred
= false;
601 wxTextAttr
attr(def
->GetStyleMergedWithBase(GetStyleSheet()));
603 if (attr
.HasAlignment() && attr
.GetAlignment() == wxTEXT_ALIGNMENT_CENTRE
)
607 str
<< wxT("<center>");
610 str
<< wxT("<table><tr>");
612 if (attr
.GetLeftIndent() > 0)
614 wxClientDC
dc((wxWindow
*) this);
616 str
<< wxT("<td width=") << wxMin(50, (ConvertTenthsMMToPixels(dc
, attr
.GetLeftIndent())/2)) << wxT("></td>");
620 str
<< wxT("<td nowrap align=\"center\">");
622 str
<< wxT("<td nowrap>");
630 // Guess a standard font size
633 // First see if we have a default/normal style to base the size on
634 wxString
normalTranslated(_("normal"));
635 wxString
defaultTranslated(_("default"));
637 for (i
= 0; i
< m_styleNames
.GetCount(); i
++)
639 wxString name
= m_styleNames
[i
].Lower();
640 if (name
.Find(wxT("normal")) != wxNOT_FOUND
|| name
.Find(normalTranslated
) != wxNOT_FOUND
||
641 name
.Find(wxT("default")) != wxNOT_FOUND
|| name
.Find(defaultTranslated
) != wxNOT_FOUND
)
643 wxRichTextStyleDefinition
* d
= GetStyleSheet()->FindStyle(m_styleNames
[i
]);
646 wxRichTextAttr
attr2(d
->GetStyleMergedWithBase(GetStyleSheet()));
647 if (attr2
.HasFontSize())
649 stdFontSize
= attr2
.GetFontSize();
656 if (stdFontSize
== 0)
658 // Look at sizes up to 20 points, and see which is the most common
661 for (i
= 0; i
<= maxSize
; i
++)
663 for (i
= 0; i
< m_styleNames
.GetCount(); i
++)
665 wxRichTextStyleDefinition
* d
= GetStyleSheet()->FindStyle(m_styleNames
[i
]);
668 wxRichTextAttr
attr2(d
->GetStyleMergedWithBase(GetStyleSheet()));
669 if (attr2
.HasFontSize())
671 if (attr2
.GetFontSize() <= (int) maxSize
)
672 sizes
[attr2
.GetFontSize()] ++;
676 int mostCommonSize
= 0;
677 for (i
= 0; i
<= maxSize
; i
++)
679 if (sizes
[i
] > mostCommonSize
)
682 if (mostCommonSize
> 0)
683 stdFontSize
= mostCommonSize
;
686 if (stdFontSize
== 0)
689 int thisFontSize
= ((attr
.GetFlags() & wxTEXT_ATTR_FONT_SIZE
) != 0) ? attr
.GetFontSize() : stdFontSize
;
691 if (thisFontSize
< stdFontSize
)
693 else if (thisFontSize
> stdFontSize
)
698 str
<< wxT(" size=") << size
;
700 if (!attr
.GetFontFaceName().IsEmpty())
701 str
<< wxT(" face=\"") << attr
.GetFontFaceName() << wxT("\"");
703 if (attr
.GetTextColour().Ok())
704 str
<< wxT(" color=\"#") << ColourToHexString(attr
.GetTextColour()) << wxT("\"");
708 bool hasBold
= false;
709 bool hasItalic
= false;
710 bool hasUnderline
= false;
712 if (attr
.GetFontWeight() == wxBOLD
)
714 if (attr
.GetFontStyle() == wxITALIC
)
716 if (attr
.GetFontUnderlined())
726 str
+= def
->GetName();
736 str
<< wxT("</centre>");
738 str
<< wxT("</font>");
740 str
<< wxT("</td></tr></table>");
743 str
<< wxT("</center>");
748 // Convert units in tends of a millimetre to device units
749 int wxRichTextStyleListBox::ConvertTenthsMMToPixels(wxDC
& dc
, int units
) const
751 int ppi
= dc
.GetPPI().x
;
753 // There are ppi pixels in 254.1 "1/10 mm"
755 double pixels
= ((double) units
* (double)ppi
) / 254.1;
760 void wxRichTextStyleListBox::OnLeftDown(wxMouseEvent
& event
)
762 wxVListBox::OnLeftDown(event
);
764 int item
= VirtualHitTest(event
.GetPosition().y
);
765 if (item
!= wxNOT_FOUND
&& GetApplyOnSelection())
769 void wxRichTextStyleListBox::OnLeftDoubleClick(wxMouseEvent
& event
)
771 wxVListBox::OnLeftDown(event
);
773 int item
= VirtualHitTest(event
.GetPosition().y
);
774 if (item
!= wxNOT_FOUND
&& !GetApplyOnSelection())
778 /// Helper for listbox and combo control
779 wxString
wxRichTextStyleListBox::GetStyleToShowInIdleTime(wxRichTextCtrl
* ctrl
, wxRichTextStyleType styleType
)
781 int adjustedCaretPos
= ctrl
->GetAdjustedCaretPosition(ctrl
->GetCaretPosition());
786 ctrl
->GetStyle(adjustedCaretPos
, attr
);
788 // Take into account current default style just chosen by user
789 if (ctrl
->IsDefaultStyleShowing())
791 wxRichTextApplyStyle(attr
, ctrl
->GetDefaultStyleEx());
793 if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_CHARACTER
) &&
794 !attr
.GetCharacterStyleName().IsEmpty())
795 styleName
= attr
.GetCharacterStyleName();
796 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_PARAGRAPH
) &&
797 !attr
.GetParagraphStyleName().IsEmpty())
798 styleName
= attr
.GetParagraphStyleName();
799 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_LIST
) &&
800 !attr
.GetListStyleName().IsEmpty())
801 styleName
= attr
.GetListStyleName();
803 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_CHARACTER
) &&
804 !attr
.GetCharacterStyleName().IsEmpty())
806 styleName
= attr
.GetCharacterStyleName();
808 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_PARAGRAPH
) &&
809 !attr
.GetParagraphStyleName().IsEmpty())
811 styleName
= attr
.GetParagraphStyleName();
813 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_LIST
) &&
814 !attr
.GetListStyleName().IsEmpty())
816 styleName
= attr
.GetListStyleName();
822 /// Auto-select from style under caret in idle time
823 void wxRichTextStyleListBox::OnIdle(wxIdleEvent
& event
)
825 if (CanAutoSetSelection() && GetRichTextCtrl() && IsShownOnScreen() && wxWindow::FindFocus() != this)
827 wxString styleName
= GetStyleToShowInIdleTime(GetRichTextCtrl(), GetStyleType());
829 int sel
= GetSelection();
830 if (!styleName
.IsEmpty())
832 // Don't do the selection if it's already set
833 if (sel
== GetIndexForStyle(styleName
))
836 SetStyleSelection(styleName
);
845 void wxRichTextStyleListBox::ApplyStyle(int item
)
847 if ( item
!= wxNOT_FOUND
)
849 wxRichTextStyleDefinition
* def
= GetStyle(item
);
850 if (def
&& GetRichTextCtrl())
852 GetRichTextCtrl()->ApplyStyle(def
);
853 GetRichTextCtrl()->SetFocus();
859 * wxRichTextStyleListCtrl class: manages a listbox and a choice control to
860 * switch shown style types
863 IMPLEMENT_CLASS(wxRichTextStyleListCtrl
, wxControl
)
865 BEGIN_EVENT_TABLE(wxRichTextStyleListCtrl
, wxControl
)
866 EVT_CHOICE(wxID_ANY
, wxRichTextStyleListCtrl::OnChooseType
)
867 EVT_SIZE(wxRichTextStyleListCtrl::OnSize
)
870 wxRichTextStyleListCtrl::wxRichTextStyleListCtrl(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
871 const wxSize
& size
, long style
)
874 Create(parent
, id
, pos
, size
, style
);
877 bool wxRichTextStyleListCtrl::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
878 const wxSize
& size
, long style
)
880 if ((style
& wxBORDER_MASK
) == wxBORDER_DEFAULT
)
881 style
|= wxBORDER_THEME
;
883 wxControl::Create(parent
, id
, pos
, size
, style
);
885 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
));
886 if (size
!= wxDefaultSize
)
887 SetInitialSize(size
);
889 bool showSelector
= ((style
& wxRICHTEXTSTYLELIST_HIDE_TYPE_SELECTOR
) == 0);
891 wxBorder listBoxStyle
;
893 listBoxStyle
= wxBORDER_THEME
;
895 listBoxStyle
= wxBORDER_NONE
;
897 m_styleListBox
= new wxRichTextStyleListBox(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, listBoxStyle
);
899 wxBoxSizer
* boxSizer
= new wxBoxSizer(wxVERTICAL
);
903 wxArrayString choices
;
904 choices
.Add(_("All styles"));
905 choices
.Add(_("Paragraph styles"));
906 choices
.Add(_("Character styles"));
907 choices
.Add(_("List styles"));
909 m_styleChoice
= new wxChoice(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, choices
);
911 boxSizer
->Add(m_styleListBox
, 1, wxALL
|wxEXPAND
, 5);
912 boxSizer
->Add(m_styleChoice
, 0, wxLEFT
|wxRIGHT
|wxBOTTOM
|wxEXPAND
, 5);
916 boxSizer
->Add(m_styleListBox
, 1, wxALL
|wxEXPAND
, 0);
926 int i
= StyleTypeToIndex(m_styleListBox
->GetStyleType());
927 m_styleChoice
->SetSelection(i
);
930 m_dontUpdate
= false;
935 wxRichTextStyleListCtrl::~wxRichTextStyleListCtrl()
940 /// React to style type choice
941 void wxRichTextStyleListCtrl::OnChooseType(wxCommandEvent
& event
)
943 if (event
.GetEventObject() != m_styleChoice
)
950 wxRichTextStyleListBox::wxRichTextStyleType styleType
= StyleIndexToType(event
.GetSelection());
951 m_styleListBox
->SetSelection(-1);
952 m_styleListBox
->SetStyleType(styleType
);
956 /// Lay out the controls
957 void wxRichTextStyleListCtrl::OnSize(wxSizeEvent
& WXUNUSED(event
))
963 /// Get the choice index for style type
964 int wxRichTextStyleListCtrl::StyleTypeToIndex(wxRichTextStyleListBox::wxRichTextStyleType styleType
)
966 if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
)
970 else if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH
)
974 else if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER
)
978 else if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST
)
985 /// Get the style type for choice index
986 wxRichTextStyleListBox::wxRichTextStyleType
wxRichTextStyleListCtrl::StyleIndexToType(int i
)
989 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH
;
991 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER
;
993 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST
;
995 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
;
998 /// Associates the control with a style manager
999 void wxRichTextStyleListCtrl::SetStyleSheet(wxRichTextStyleSheet
* styleSheet
)
1002 m_styleListBox
->SetStyleSheet(styleSheet
);
1005 wxRichTextStyleSheet
* wxRichTextStyleListCtrl::GetStyleSheet() const
1008 return m_styleListBox
->GetStyleSheet();
1013 /// Associates the control with a wxRichTextCtrl
1014 void wxRichTextStyleListCtrl::SetRichTextCtrl(wxRichTextCtrl
* ctrl
)
1017 m_styleListBox
->SetRichTextCtrl(ctrl
);
1020 wxRichTextCtrl
* wxRichTextStyleListCtrl::GetRichTextCtrl() const
1023 return m_styleListBox
->GetRichTextCtrl();
1028 /// Set/get the style type to display
1029 void wxRichTextStyleListCtrl::SetStyleType(wxRichTextStyleListBox::wxRichTextStyleType styleType
)
1031 if ( !m_styleListBox
)
1034 m_styleListBox
->SetStyleType(styleType
);
1036 m_dontUpdate
= true;
1040 int i
= StyleTypeToIndex(m_styleListBox
->GetStyleType());
1041 m_styleChoice
->SetSelection(i
);
1044 m_dontUpdate
= false;
1047 wxRichTextStyleListBox::wxRichTextStyleType
wxRichTextStyleListCtrl::GetStyleType() const
1050 return m_styleListBox
->GetStyleType();
1052 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
;
1055 /// Updates the style list box
1056 void wxRichTextStyleListCtrl::UpdateStyles()
1059 m_styleListBox
->UpdateStyles();
1065 * Style drop-down for a wxComboCtrl
1069 BEGIN_EVENT_TABLE(wxRichTextStyleComboPopup
, wxRichTextStyleListBox
)
1070 EVT_MOTION(wxRichTextStyleComboPopup::OnMouseMove
)
1071 EVT_LEFT_DOWN(wxRichTextStyleComboPopup::OnMouseClick
)
1074 bool wxRichTextStyleComboPopup::Create( wxWindow
* parent
)
1076 int borderStyle
= GetDefaultBorder();
1077 if (borderStyle
== wxBORDER_SUNKEN
)
1078 borderStyle
= wxBORDER_SIMPLE
;
1080 return wxRichTextStyleListBox::Create(parent
, wxID_ANY
,
1081 wxPoint(0,0), wxDefaultSize
,
1085 void wxRichTextStyleComboPopup::SetStringValue( const wxString
& s
)
1087 m_value
= SetStyleSelection(s
);
1090 wxString
wxRichTextStyleComboPopup::GetStringValue() const
1095 wxRichTextStyleDefinition
* def
= GetStyle(sel
);
1097 return def
->GetName();
1099 return wxEmptyString
;
1103 // Popup event handlers
1106 // Mouse hot-tracking
1107 void wxRichTextStyleComboPopup::OnMouseMove(wxMouseEvent
& event
)
1109 // Move selection to cursor if it is inside the popup
1111 int itemHere
= wxRichTextStyleListBox::VirtualHitTest(event
.GetPosition().y
);
1112 if ( itemHere
>= 0 )
1114 wxRichTextStyleListBox::SetSelection(itemHere
);
1115 m_itemHere
= itemHere
;
1120 // On mouse left, set the value and close the popup
1121 void wxRichTextStyleComboPopup::OnMouseClick(wxMouseEvent
& WXUNUSED(event
))
1123 if (m_itemHere
>= 0)
1124 m_value
= m_itemHere
;
1126 // Ordering is important, so we don't dismiss this popup accidentally
1127 // by setting the focus elsewhere e.g. in ApplyStyle
1130 if (m_itemHere
>= 0)
1131 wxRichTextStyleListBox::ApplyStyle(m_itemHere
);
1135 * wxRichTextStyleComboCtrl
1136 * A combo for applying styles.
1139 IMPLEMENT_CLASS(wxRichTextStyleComboCtrl
, wxComboCtrl
)
1141 BEGIN_EVENT_TABLE(wxRichTextStyleComboCtrl
, wxComboCtrl
)
1142 EVT_IDLE(wxRichTextStyleComboCtrl::OnIdle
)
1145 bool wxRichTextStyleComboCtrl::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
1146 const wxSize
& size
, long style
)
1148 if (!wxComboCtrl::Create(parent
, id
, wxEmptyString
, pos
, size
, style
))
1151 SetPopupMaxHeight(400);
1153 m_stylePopup
= new wxRichTextStyleComboPopup
;
1155 SetPopupControl(m_stylePopup
);
1160 /// Auto-select from style under caret in idle time
1162 // TODO: must be able to show italic, bold, combinations
1163 // in style box. Do we have a concept of automatic, temporary
1164 // styles that are added whenever we wish to show a style
1165 // that doesn't exist already? E.g. "Bold, Italic, Underline".
1166 // Word seems to generate these things on the fly.
1167 // If there's a named style already, it uses e.g. Heading1 + Bold, Italic
1168 // If you unembolden text in a style that has bold, it uses the
1170 // TODO: order styles alphabetically. This means indexes can change,
1171 // so need a different way to specify selections, i.e. by name.
1173 void wxRichTextStyleComboCtrl::OnIdle(wxIdleEvent
& event
)
1177 if ( !m_stylePopup
)
1180 wxRichTextCtrl
* const richtext
= GetRichTextCtrl();
1184 if ( !IsPopupShown() && IsShownOnScreen() && wxWindow::FindFocus() != this )
1186 wxString styleName
=
1187 wxRichTextStyleListBox::GetStyleToShowInIdleTime(richtext
, m_stylePopup
->GetStyleType());
1189 wxString currentValue
= GetValue();
1190 if (!styleName
.IsEmpty())
1192 // Don't do the selection if it's already set
1193 if (currentValue
== styleName
)
1196 SetValue(styleName
);
1198 else if (!currentValue
.IsEmpty())
1199 SetValue(wxEmptyString
);