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())
62 // Collect the styles, detecting loops
63 wxArrayString styleNames
;
65 const wxRichTextStyleDefinition
* def
= this;
68 styles
.Insert((wxObject
*) def
);
69 styleNames
.Add(def
->GetName());
71 wxString baseStyleName
= def
->GetBaseStyle();
72 if (!baseStyleName
.IsEmpty() && styleNames
.Index(baseStyleName
) == wxNOT_FOUND
)
73 def
= sheet
->FindStyle(baseStyleName
);
79 wxList::compatibility_iterator node
= styles
.GetFirst();
82 wxRichTextStyleDefinition
* def
= (wxRichTextStyleDefinition
*) node
->GetData();
83 attr
.Apply(def
->GetStyle(), NULL
);
84 node
= node
->GetNext();
91 * Paragraph style definition
94 void wxRichTextParagraphStyleDefinition::Copy(const wxRichTextParagraphStyleDefinition
& def
)
96 wxRichTextStyleDefinition::Copy(def
);
98 m_nextStyle
= def
.m_nextStyle
;
101 bool wxRichTextParagraphStyleDefinition::operator ==(const wxRichTextParagraphStyleDefinition
& def
) const
103 return (Eq(def
) && m_nextStyle
== def
.m_nextStyle
);
107 * List style definition
110 void wxRichTextListStyleDefinition::Copy(const wxRichTextListStyleDefinition
& def
)
112 wxRichTextParagraphStyleDefinition::Copy(def
);
115 for (i
= 0; i
< 10; i
++)
116 m_levelStyles
[i
] = def
.m_levelStyles
[i
];
119 bool wxRichTextListStyleDefinition::operator ==(const wxRichTextListStyleDefinition
& def
) const
124 for (i
= 0; i
< 10; i
++)
125 if (!(m_levelStyles
[i
] == def
.m_levelStyles
[i
]))
131 /// Sets/gets the attributes for the given level
132 void wxRichTextListStyleDefinition::SetLevelAttributes(int i
, const wxTextAttr
& attr
)
134 wxASSERT( (i
>= 0 && i
< 10) );
135 if (i
>= 0 && i
< 10)
136 m_levelStyles
[i
] = attr
;
139 const wxTextAttr
* wxRichTextListStyleDefinition::GetLevelAttributes(int i
) const
141 wxASSERT( (i
>= 0 && i
< 10) );
142 if (i
>= 0 && i
< 10)
143 return & m_levelStyles
[i
];
148 wxTextAttr
* wxRichTextListStyleDefinition::GetLevelAttributes(int i
)
150 wxASSERT( (i
>= 0 && i
< 10) );
151 if (i
>= 0 && i
< 10)
152 return & m_levelStyles
[i
];
157 /// Convenience function for setting the major attributes for a list level specification
158 void wxRichTextListStyleDefinition::SetAttributes(int i
, int leftIndent
, int leftSubIndent
, int bulletStyle
, const wxString
& bulletSymbol
)
160 wxASSERT( (i
>= 0 && i
< 10) );
161 if (i
>= 0 && i
< 10)
165 attr
.SetBulletStyle(bulletStyle
);
166 attr
.SetLeftIndent(leftIndent
, leftSubIndent
);
168 if (!bulletSymbol
.IsEmpty())
170 if (bulletStyle
& wxTEXT_ATTR_BULLET_STYLE_SYMBOL
)
171 attr
.SetBulletText(bulletSymbol
);
173 attr
.SetBulletName(bulletSymbol
);
176 m_levelStyles
[i
] = attr
;
180 /// Finds the level corresponding to the given indentation
181 int wxRichTextListStyleDefinition::FindLevelForIndent(int indent
) const
184 for (i
= 0; i
< 10; i
++)
186 if (indent
< m_levelStyles
[i
].GetLeftIndent())
197 /// Combine the list style with a paragraph style, using the given indent (from which
198 /// an appropriate level is found)
199 wxTextAttr
wxRichTextListStyleDefinition::CombineWithParagraphStyle(int indent
, const wxTextAttr
& paraStyle
, wxRichTextStyleSheet
* styleSheet
)
201 int listLevel
= FindLevelForIndent(indent
);
203 wxTextAttr
attr(*GetLevelAttributes(listLevel
));
204 int oldLeftIndent
= attr
.GetLeftIndent();
205 int oldLeftSubIndent
= attr
.GetLeftSubIndent();
207 // First apply the overall paragraph style, if any
209 attr
.Apply(GetStyleMergedWithBase(styleSheet
));
211 attr
.Apply(GetStyle());
213 // Then apply paragraph style, e.g. from paragraph style definition
214 attr
.Apply(paraStyle
);
216 // We override the indents according to the list definition
217 attr
.SetLeftIndent(oldLeftIndent
, oldLeftSubIndent
);
222 /// Combine the base and list style, using the given indent (from which
223 /// an appropriate level is found)
224 wxTextAttr
wxRichTextListStyleDefinition::GetCombinedStyle(int indent
, wxRichTextStyleSheet
* styleSheet
)
226 int listLevel
= FindLevelForIndent(indent
);
227 return GetCombinedStyleForLevel(listLevel
, styleSheet
);
230 /// Combine the base and list style, using the given indent (from which
231 /// an appropriate level is found)
232 wxTextAttr
wxRichTextListStyleDefinition::GetCombinedStyleForLevel(int listLevel
, wxRichTextStyleSheet
* styleSheet
)
234 wxTextAttr
attr(*GetLevelAttributes(listLevel
));
235 int oldLeftIndent
= attr
.GetLeftIndent();
236 int oldLeftSubIndent
= attr
.GetLeftSubIndent();
238 // Apply the overall paragraph style, if any
240 attr
.Apply(GetStyleMergedWithBase(styleSheet
));
242 attr
.Apply(GetStyle());
244 // We override the indents according to the list definition
245 attr
.SetLeftIndent(oldLeftIndent
, oldLeftSubIndent
);
250 /// Is this a numbered list?
251 bool wxRichTextListStyleDefinition::IsNumbered(int i
) const
253 return (0 != (GetLevelAttributes(i
)->GetFlags() &
254 (wxTEXT_ATTR_BULLET_STYLE_ARABIC
|wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER
|wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER
|
255 wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER
|wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER
)));
262 IMPLEMENT_CLASS(wxRichTextStyleSheet
, wxObject
)
264 wxRichTextStyleSheet::~wxRichTextStyleSheet()
269 m_nextSheet
->m_previousSheet
= m_previousSheet
;
272 m_previousSheet
->m_nextSheet
= m_nextSheet
;
274 m_previousSheet
= NULL
;
279 void wxRichTextStyleSheet::Init()
281 m_previousSheet
= NULL
;
285 /// Add a definition to one of the style lists
286 bool wxRichTextStyleSheet::AddStyle(wxList
& list
, wxRichTextStyleDefinition
* def
)
294 bool wxRichTextStyleSheet::RemoveStyle(wxList
& list
, wxRichTextStyleDefinition
* def
, bool deleteStyle
)
296 wxList::compatibility_iterator node
= list
.Find(def
);
299 wxRichTextStyleDefinition
* def
= (wxRichTextStyleDefinition
*) node
->GetData();
310 bool wxRichTextStyleSheet::RemoveStyle(wxRichTextStyleDefinition
* def
, bool deleteStyle
)
312 if (RemoveParagraphStyle(def
, deleteStyle
))
314 if (RemoveCharacterStyle(def
, deleteStyle
))
316 if (RemoveListStyle(def
, deleteStyle
))
321 /// Find a definition by name
322 wxRichTextStyleDefinition
* wxRichTextStyleSheet::FindStyle(const wxList
& list
, const wxString
& name
, bool recurse
) const
324 for (wxList::compatibility_iterator node
= list
.GetFirst(); node
; node
= node
->GetNext())
326 wxRichTextStyleDefinition
* def
= (wxRichTextStyleDefinition
*) node
->GetData();
327 if (def
->GetName().Lower() == name
.Lower())
331 if (m_nextSheet
&& recurse
)
332 return m_nextSheet
->FindStyle(list
, name
, recurse
);
337 /// Delete all styles
338 void wxRichTextStyleSheet::DeleteStyles()
340 WX_CLEAR_LIST(wxList
, m_characterStyleDefinitions
);
341 WX_CLEAR_LIST(wxList
, m_paragraphStyleDefinitions
);
342 WX_CLEAR_LIST(wxList
, m_listStyleDefinitions
);
345 /// Insert into list of style sheets
346 bool wxRichTextStyleSheet::InsertSheet(wxRichTextStyleSheet
* before
)
348 m_previousSheet
= before
->m_previousSheet
;
349 m_nextSheet
= before
;
351 before
->m_previousSheet
= this;
355 /// Append to list of style sheets
356 bool wxRichTextStyleSheet::AppendSheet(wxRichTextStyleSheet
* after
)
358 wxRichTextStyleSheet
* last
= after
;
359 while (last
&& last
->m_nextSheet
)
361 last
= last
->m_nextSheet
;
366 m_previousSheet
= last
;
367 last
->m_nextSheet
= this;
375 /// Unlink from the list of style sheets
376 void wxRichTextStyleSheet::Unlink()
379 m_previousSheet
->m_nextSheet
= m_nextSheet
;
381 m_nextSheet
->m_previousSheet
= m_previousSheet
;
383 m_previousSheet
= NULL
;
387 /// Add a definition to the character style list
388 bool wxRichTextStyleSheet::AddCharacterStyle(wxRichTextCharacterStyleDefinition
* def
)
390 def
->GetStyle().SetCharacterStyleName(def
->GetName());
391 return AddStyle(m_characterStyleDefinitions
, def
);
394 /// Add a definition to the paragraph style list
395 bool wxRichTextStyleSheet::AddParagraphStyle(wxRichTextParagraphStyleDefinition
* def
)
397 def
->GetStyle().SetParagraphStyleName(def
->GetName());
398 return AddStyle(m_paragraphStyleDefinitions
, def
);
401 /// Add a definition to the list style list
402 bool wxRichTextStyleSheet::AddListStyle(wxRichTextListStyleDefinition
* def
)
404 def
->GetStyle().SetListStyleName(def
->GetName());
405 return AddStyle(m_listStyleDefinitions
, def
);
408 /// Add a definition to the appropriate style list
409 bool wxRichTextStyleSheet::AddStyle(wxRichTextStyleDefinition
* def
)
411 wxRichTextListStyleDefinition
* listDef
= wxDynamicCast(def
, wxRichTextListStyleDefinition
);
413 return AddListStyle(listDef
);
415 wxRichTextParagraphStyleDefinition
* paraDef
= wxDynamicCast(def
, wxRichTextParagraphStyleDefinition
);
417 return AddParagraphStyle(paraDef
);
419 wxRichTextCharacterStyleDefinition
* charDef
= wxDynamicCast(def
, wxRichTextCharacterStyleDefinition
);
421 return AddCharacterStyle(charDef
);
426 /// Find any definition by name
427 wxRichTextStyleDefinition
* wxRichTextStyleSheet::FindStyle(const wxString
& name
, bool recurse
) const
429 wxRichTextListStyleDefinition
* listDef
= FindListStyle(name
, recurse
);
433 wxRichTextParagraphStyleDefinition
* paraDef
= FindParagraphStyle(name
, recurse
);
437 wxRichTextCharacterStyleDefinition
* charDef
= FindCharacterStyle(name
, recurse
);
445 void wxRichTextStyleSheet::Copy(const wxRichTextStyleSheet
& sheet
)
449 wxList::compatibility_iterator node
;
451 for (node
= sheet
.m_characterStyleDefinitions
.GetFirst(); node
; node
= node
->GetNext())
453 wxRichTextCharacterStyleDefinition
* def
= (wxRichTextCharacterStyleDefinition
*) node
->GetData();
454 AddCharacterStyle(new wxRichTextCharacterStyleDefinition(*def
));
457 for (node
= sheet
.m_paragraphStyleDefinitions
.GetFirst(); node
; node
= node
->GetNext())
459 wxRichTextParagraphStyleDefinition
* def
= (wxRichTextParagraphStyleDefinition
*) node
->GetData();
460 AddParagraphStyle(new wxRichTextParagraphStyleDefinition(*def
));
463 for (node
= sheet
.m_listStyleDefinitions
.GetFirst(); node
; node
= node
->GetNext())
465 wxRichTextListStyleDefinition
* def
= (wxRichTextListStyleDefinition
*) node
->GetData();
466 AddListStyle(new wxRichTextListStyleDefinition(*def
));
469 SetName(sheet
.GetName());
470 SetDescription(sheet
.GetDescription());
474 bool wxRichTextStyleSheet::operator==(const wxRichTextStyleSheet
& WXUNUSED(sheet
)) const
483 * wxRichTextStyleListBox: a listbox to display styles.
486 IMPLEMENT_CLASS(wxRichTextStyleListBox
, wxHtmlListBox
)
488 BEGIN_EVENT_TABLE(wxRichTextStyleListBox
, wxHtmlListBox
)
489 EVT_LEFT_DOWN(wxRichTextStyleListBox::OnLeftDown
)
490 EVT_LEFT_DCLICK(wxRichTextStyleListBox::OnLeftDoubleClick
)
491 EVT_IDLE(wxRichTextStyleListBox::OnIdle
)
494 wxRichTextStyleListBox::wxRichTextStyleListBox(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
495 const wxSize
& size
, long style
)
498 Create(parent
, id
, pos
, size
, style
);
501 bool wxRichTextStyleListBox::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
502 const wxSize
& size
, long style
)
504 return wxHtmlListBox::Create(parent
, id
, pos
, size
, style
);
507 wxRichTextStyleListBox::~wxRichTextStyleListBox()
511 /// Returns the HTML for this item
512 wxString
wxRichTextStyleListBox::OnGetItem(size_t n
) const
514 if (!GetStyleSheet())
515 return wxEmptyString
;
517 wxRichTextStyleDefinition
* def
= GetStyle(n
);
519 return CreateHTML(def
);
521 return wxEmptyString
;
524 // Get style for index
525 wxRichTextStyleDefinition
* wxRichTextStyleListBox::GetStyle(size_t i
) const
527 if (!GetStyleSheet())
530 if (i
>= m_styleNames
.GetCount() /* || i < 0 */ )
533 return GetStyleSheet()->FindStyle(m_styleNames
[i
]);
537 void wxRichTextStyleListBox::UpdateStyles()
541 int oldSel
= GetSelection();
543 SetSelection(wxNOT_FOUND
);
545 m_styleNames
.Clear();
548 if (GetStyleType() == wxRICHTEXT_STYLE_ALL
|| GetStyleType() == wxRICHTEXT_STYLE_PARAGRAPH
)
550 for (i
= 0; i
< GetStyleSheet()->GetParagraphStyleCount(); i
++)
551 m_styleNames
.Add(GetStyleSheet()->GetParagraphStyle(i
)->GetName());
553 if (GetStyleType() == wxRICHTEXT_STYLE_ALL
|| GetStyleType() == wxRICHTEXT_STYLE_CHARACTER
)
555 for (i
= 0; i
< GetStyleSheet()->GetCharacterStyleCount(); i
++)
556 m_styleNames
.Add(GetStyleSheet()->GetCharacterStyle(i
)->GetName());
558 if (GetStyleType() == wxRICHTEXT_STYLE_ALL
|| GetStyleType() == wxRICHTEXT_STYLE_LIST
)
560 for (i
= 0; i
< GetStyleSheet()->GetListStyleCount(); i
++)
561 m_styleNames
.Add(GetStyleSheet()->GetListStyle(i
)->GetName());
565 SetItemCount(m_styleNames
.GetCount());
570 if (oldSel
>= 0 && oldSel
< (int) GetItemCount())
572 else if (GetItemCount() > 0)
577 SetSelection(newSel
);
583 // Get index for style name
584 int wxRichTextStyleListBox::GetIndexForStyle(const wxString
& name
) const
586 return m_styleNames
.Index(name
);
589 /// Set selection for string
590 int wxRichTextStyleListBox::SetStyleSelection(const wxString
& name
)
592 int i
= GetIndexForStyle(name
);
598 // Convert a colour to a 6-digit hex string
599 static wxString
ColourToHexString(const wxColour
& col
)
603 hex
+= wxDecToHex(col
.Red());
604 hex
+= wxDecToHex(col
.Green());
605 hex
+= wxDecToHex(col
.Blue());
610 /// Creates a suitable HTML fragment for a definition
611 wxString
wxRichTextStyleListBox::CreateHTML(wxRichTextStyleDefinition
* def
) const
613 // TODO: indicate list format for list style types
617 bool isCentred
= false;
619 wxTextAttr
attr(def
->GetStyleMergedWithBase(GetStyleSheet()));
621 if (attr
.HasAlignment() && attr
.GetAlignment() == wxTEXT_ALIGNMENT_CENTRE
)
625 str
<< wxT("<center>");
628 str
<< wxT("<table><tr>");
630 if (attr
.GetLeftIndent() > 0)
632 wxClientDC
dc((wxWindow
*) this);
634 str
<< wxT("<td width=") << wxMin(50, (ConvertTenthsMMToPixels(dc
, attr
.GetLeftIndent())/2)) << wxT("></td>");
638 str
<< wxT("<td nowrap align=\"center\">");
640 str
<< wxT("<td nowrap>");
648 // Guess a standard font size
651 // First see if we have a default/normal style to base the size on
652 wxString
normalTranslated(_("normal"));
653 wxString
defaultTranslated(_("default"));
655 for (i
= 0; i
< m_styleNames
.GetCount(); i
++)
657 wxString name
= m_styleNames
[i
].Lower();
658 if (name
.Find(wxT("normal")) != wxNOT_FOUND
|| name
.Find(normalTranslated
) != wxNOT_FOUND
||
659 name
.Find(wxT("default")) != wxNOT_FOUND
|| name
.Find(defaultTranslated
) != wxNOT_FOUND
)
661 wxRichTextStyleDefinition
* d
= GetStyleSheet()->FindStyle(m_styleNames
[i
]);
664 wxRichTextAttr
attr2(d
->GetStyleMergedWithBase(GetStyleSheet()));
665 if (attr2
.HasFontSize())
667 stdFontSize
= attr2
.GetFontSize();
674 if (stdFontSize
== 0)
676 // Look at sizes up to 20 points, and see which is the most common
679 for (i
= 0; i
<= maxSize
; i
++)
681 for (i
= 0; i
< m_styleNames
.GetCount(); i
++)
683 wxRichTextStyleDefinition
* d
= GetStyleSheet()->FindStyle(m_styleNames
[i
]);
686 wxRichTextAttr
attr2(d
->GetStyleMergedWithBase(GetStyleSheet()));
687 if (attr2
.HasFontSize())
689 if (attr2
.GetFontSize() <= (int) maxSize
)
690 sizes
[attr2
.GetFontSize()] ++;
694 int mostCommonSize
= 0;
695 for (i
= 0; i
<= maxSize
; i
++)
697 if (sizes
[i
] > mostCommonSize
)
700 if (mostCommonSize
> 0)
701 stdFontSize
= mostCommonSize
;
704 if (stdFontSize
== 0)
707 int thisFontSize
= ((attr
.GetFlags() & wxTEXT_ATTR_FONT_SIZE
) != 0) ? attr
.GetFontSize() : stdFontSize
;
709 if (thisFontSize
< stdFontSize
)
711 else if (thisFontSize
> stdFontSize
)
716 str
<< wxT(" size=") << size
;
718 if (!attr
.GetFontFaceName().IsEmpty())
719 str
<< wxT(" face=\"") << attr
.GetFontFaceName() << wxT("\"");
721 if (attr
.GetTextColour().Ok())
722 str
<< wxT(" color=\"#") << ColourToHexString(attr
.GetTextColour()) << wxT("\"");
726 bool hasBold
= false;
727 bool hasItalic
= false;
728 bool hasUnderline
= false;
730 if (attr
.GetFontWeight() == wxBOLD
)
732 if (attr
.GetFontStyle() == wxITALIC
)
734 if (attr
.GetFontUnderlined())
744 str
+= def
->GetName();
754 str
<< wxT("</centre>");
756 str
<< wxT("</font>");
758 str
<< wxT("</td></tr></table>");
761 str
<< wxT("</center>");
766 // Convert units in tends of a millimetre to device units
767 int wxRichTextStyleListBox::ConvertTenthsMMToPixels(wxDC
& dc
, int units
) const
769 int ppi
= dc
.GetPPI().x
;
771 // There are ppi pixels in 254.1 "1/10 mm"
773 double pixels
= ((double) units
* (double)ppi
) / 254.1;
778 void wxRichTextStyleListBox::OnLeftDown(wxMouseEvent
& event
)
780 wxVListBox::OnLeftDown(event
);
782 int item
= VirtualHitTest(event
.GetPosition().y
);
783 if (item
!= wxNOT_FOUND
&& GetApplyOnSelection())
787 void wxRichTextStyleListBox::OnLeftDoubleClick(wxMouseEvent
& event
)
789 wxVListBox::OnLeftDown(event
);
791 int item
= VirtualHitTest(event
.GetPosition().y
);
792 if (item
!= wxNOT_FOUND
&& !GetApplyOnSelection())
796 /// Helper for listbox and combo control
797 wxString
wxRichTextStyleListBox::GetStyleToShowInIdleTime(wxRichTextCtrl
* ctrl
, wxRichTextStyleType styleType
)
799 int adjustedCaretPos
= ctrl
->GetAdjustedCaretPosition(ctrl
->GetCaretPosition());
804 ctrl
->GetStyle(adjustedCaretPos
, attr
);
806 // Take into account current default style just chosen by user
807 if (ctrl
->IsDefaultStyleShowing())
809 wxRichTextApplyStyle(attr
, ctrl
->GetDefaultStyleEx());
811 if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_CHARACTER
) &&
812 !attr
.GetCharacterStyleName().IsEmpty())
813 styleName
= attr
.GetCharacterStyleName();
814 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_PARAGRAPH
) &&
815 !attr
.GetParagraphStyleName().IsEmpty())
816 styleName
= attr
.GetParagraphStyleName();
817 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_LIST
) &&
818 !attr
.GetListStyleName().IsEmpty())
819 styleName
= attr
.GetListStyleName();
821 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_CHARACTER
) &&
822 !attr
.GetCharacterStyleName().IsEmpty())
824 styleName
= attr
.GetCharacterStyleName();
826 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_PARAGRAPH
) &&
827 !attr
.GetParagraphStyleName().IsEmpty())
829 styleName
= attr
.GetParagraphStyleName();
831 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_LIST
) &&
832 !attr
.GetListStyleName().IsEmpty())
834 styleName
= attr
.GetListStyleName();
840 /// Auto-select from style under caret in idle time
841 void wxRichTextStyleListBox::OnIdle(wxIdleEvent
& event
)
843 if (CanAutoSetSelection() && GetRichTextCtrl() && IsShownOnScreen() && wxWindow::FindFocus() != this)
845 wxString styleName
= GetStyleToShowInIdleTime(GetRichTextCtrl(), GetStyleType());
847 int sel
= GetSelection();
848 if (!styleName
.IsEmpty())
850 // Don't do the selection if it's already set
851 if (sel
== GetIndexForStyle(styleName
))
854 SetStyleSelection(styleName
);
863 void wxRichTextStyleListBox::ApplyStyle(int item
)
865 if ( item
!= wxNOT_FOUND
)
867 wxRichTextStyleDefinition
* def
= GetStyle(item
);
868 if (def
&& GetRichTextCtrl())
870 GetRichTextCtrl()->ApplyStyle(def
);
871 GetRichTextCtrl()->SetFocus();
877 * wxRichTextStyleListCtrl class: manages a listbox and a choice control to
878 * switch shown style types
881 IMPLEMENT_CLASS(wxRichTextStyleListCtrl
, wxControl
)
883 BEGIN_EVENT_TABLE(wxRichTextStyleListCtrl
, wxControl
)
884 EVT_CHOICE(wxID_ANY
, wxRichTextStyleListCtrl::OnChooseType
)
885 EVT_SIZE(wxRichTextStyleListCtrl::OnSize
)
888 wxRichTextStyleListCtrl::wxRichTextStyleListCtrl(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
889 const wxSize
& size
, long style
)
892 Create(parent
, id
, pos
, size
, style
);
895 bool wxRichTextStyleListCtrl::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
896 const wxSize
& size
, long style
)
898 if ((style
& wxBORDER_MASK
) == wxBORDER_DEFAULT
)
899 style
|= wxBORDER_THEME
;
901 wxControl::Create(parent
, id
, pos
, size
, style
);
903 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
));
904 if (size
!= wxDefaultSize
)
905 SetInitialSize(size
);
907 bool showSelector
= ((style
& wxRICHTEXTSTYLELIST_HIDE_TYPE_SELECTOR
) == 0);
909 wxBorder listBoxStyle
;
911 listBoxStyle
= wxBORDER_THEME
;
913 listBoxStyle
= wxBORDER_NONE
;
915 m_styleListBox
= new wxRichTextStyleListBox(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, listBoxStyle
);
917 wxBoxSizer
* boxSizer
= new wxBoxSizer(wxVERTICAL
);
921 wxArrayString choices
;
922 choices
.Add(_("All styles"));
923 choices
.Add(_("Paragraph styles"));
924 choices
.Add(_("Character styles"));
925 choices
.Add(_("List styles"));
927 m_styleChoice
= new wxChoice(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, choices
);
929 boxSizer
->Add(m_styleListBox
, 1, wxALL
|wxEXPAND
, 5);
930 boxSizer
->Add(m_styleChoice
, 0, wxLEFT
|wxRIGHT
|wxBOTTOM
|wxEXPAND
, 5);
934 boxSizer
->Add(m_styleListBox
, 1, wxALL
|wxEXPAND
, 0);
944 int i
= StyleTypeToIndex(m_styleListBox
->GetStyleType());
945 m_styleChoice
->SetSelection(i
);
948 m_dontUpdate
= false;
953 wxRichTextStyleListCtrl::~wxRichTextStyleListCtrl()
958 /// React to style type choice
959 void wxRichTextStyleListCtrl::OnChooseType(wxCommandEvent
& event
)
961 if (event
.GetEventObject() != m_styleChoice
)
968 wxRichTextStyleListBox::wxRichTextStyleType styleType
= StyleIndexToType(event
.GetSelection());
969 m_styleListBox
->SetSelection(-1);
970 m_styleListBox
->SetStyleType(styleType
);
974 /// Lay out the controls
975 void wxRichTextStyleListCtrl::OnSize(wxSizeEvent
& WXUNUSED(event
))
981 /// Get the choice index for style type
982 int wxRichTextStyleListCtrl::StyleTypeToIndex(wxRichTextStyleListBox::wxRichTextStyleType styleType
)
984 if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
)
988 else if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH
)
992 else if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER
)
996 else if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST
)
1003 /// Get the style type for choice index
1004 wxRichTextStyleListBox::wxRichTextStyleType
wxRichTextStyleListCtrl::StyleIndexToType(int i
)
1007 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH
;
1009 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER
;
1011 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST
;
1013 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
;
1016 /// Associates the control with a style manager
1017 void wxRichTextStyleListCtrl::SetStyleSheet(wxRichTextStyleSheet
* styleSheet
)
1020 m_styleListBox
->SetStyleSheet(styleSheet
);
1023 wxRichTextStyleSheet
* wxRichTextStyleListCtrl::GetStyleSheet() const
1026 return m_styleListBox
->GetStyleSheet();
1031 /// Associates the control with a wxRichTextCtrl
1032 void wxRichTextStyleListCtrl::SetRichTextCtrl(wxRichTextCtrl
* ctrl
)
1035 m_styleListBox
->SetRichTextCtrl(ctrl
);
1038 wxRichTextCtrl
* wxRichTextStyleListCtrl::GetRichTextCtrl() const
1041 return m_styleListBox
->GetRichTextCtrl();
1046 /// Set/get the style type to display
1047 void wxRichTextStyleListCtrl::SetStyleType(wxRichTextStyleListBox::wxRichTextStyleType styleType
)
1049 if ( !m_styleListBox
)
1052 m_styleListBox
->SetStyleType(styleType
);
1054 m_dontUpdate
= true;
1058 int i
= StyleTypeToIndex(m_styleListBox
->GetStyleType());
1059 m_styleChoice
->SetSelection(i
);
1062 m_dontUpdate
= false;
1065 wxRichTextStyleListBox::wxRichTextStyleType
wxRichTextStyleListCtrl::GetStyleType() const
1068 return m_styleListBox
->GetStyleType();
1070 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
;
1073 /// Updates the style list box
1074 void wxRichTextStyleListCtrl::UpdateStyles()
1077 m_styleListBox
->UpdateStyles();
1083 * Style drop-down for a wxComboCtrl
1087 BEGIN_EVENT_TABLE(wxRichTextStyleComboPopup
, wxRichTextStyleListBox
)
1088 EVT_MOTION(wxRichTextStyleComboPopup::OnMouseMove
)
1089 EVT_LEFT_DOWN(wxRichTextStyleComboPopup::OnMouseClick
)
1092 bool wxRichTextStyleComboPopup::Create( wxWindow
* parent
)
1094 int borderStyle
= GetDefaultBorder();
1095 if (borderStyle
== wxBORDER_SUNKEN
)
1096 borderStyle
= wxBORDER_SIMPLE
;
1098 return wxRichTextStyleListBox::Create(parent
, wxID_ANY
,
1099 wxPoint(0,0), wxDefaultSize
,
1103 void wxRichTextStyleComboPopup::SetStringValue( const wxString
& s
)
1105 m_value
= SetStyleSelection(s
);
1108 wxString
wxRichTextStyleComboPopup::GetStringValue() const
1113 wxRichTextStyleDefinition
* def
= GetStyle(sel
);
1115 return def
->GetName();
1117 return wxEmptyString
;
1121 // Popup event handlers
1124 // Mouse hot-tracking
1125 void wxRichTextStyleComboPopup::OnMouseMove(wxMouseEvent
& event
)
1127 // Move selection to cursor if it is inside the popup
1129 int itemHere
= wxRichTextStyleListBox::VirtualHitTest(event
.GetPosition().y
);
1130 if ( itemHere
>= 0 )
1132 wxRichTextStyleListBox::SetSelection(itemHere
);
1133 m_itemHere
= itemHere
;
1138 // On mouse left, set the value and close the popup
1139 void wxRichTextStyleComboPopup::OnMouseClick(wxMouseEvent
& WXUNUSED(event
))
1141 if (m_itemHere
>= 0)
1142 m_value
= m_itemHere
;
1144 // Ordering is important, so we don't dismiss this popup accidentally
1145 // by setting the focus elsewhere e.g. in ApplyStyle
1148 if (m_itemHere
>= 0)
1149 wxRichTextStyleListBox::ApplyStyle(m_itemHere
);
1153 * wxRichTextStyleComboCtrl
1154 * A combo for applying styles.
1157 IMPLEMENT_CLASS(wxRichTextStyleComboCtrl
, wxComboCtrl
)
1159 BEGIN_EVENT_TABLE(wxRichTextStyleComboCtrl
, wxComboCtrl
)
1160 EVT_IDLE(wxRichTextStyleComboCtrl::OnIdle
)
1163 bool wxRichTextStyleComboCtrl::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
1164 const wxSize
& size
, long style
)
1166 if (!wxComboCtrl::Create(parent
, id
, wxEmptyString
, pos
, size
, style
))
1169 SetPopupMaxHeight(400);
1171 m_stylePopup
= new wxRichTextStyleComboPopup
;
1173 SetPopupControl(m_stylePopup
);
1178 /// Auto-select from style under caret in idle time
1180 // TODO: must be able to show italic, bold, combinations
1181 // in style box. Do we have a concept of automatic, temporary
1182 // styles that are added whenever we wish to show a style
1183 // that doesn't exist already? E.g. "Bold, Italic, Underline".
1184 // Word seems to generate these things on the fly.
1185 // If there's a named style already, it uses e.g. Heading1 + Bold, Italic
1186 // If you unembolden text in a style that has bold, it uses the
1188 // TODO: order styles alphabetically. This means indexes can change,
1189 // so need a different way to specify selections, i.e. by name.
1191 void wxRichTextStyleComboCtrl::OnIdle(wxIdleEvent
& event
)
1195 if ( !m_stylePopup
)
1198 wxRichTextCtrl
* const richtext
= GetRichTextCtrl();
1202 if ( !IsPopupShown() && IsShownOnScreen() && wxWindow::FindFocus() != this )
1204 wxString styleName
=
1205 wxRichTextStyleListBox::GetStyleToShowInIdleTime(richtext
, m_stylePopup
->GetStyleType());
1207 wxString currentValue
= GetValue();
1208 if (!styleName
.IsEmpty())
1210 // Don't do the selection if it's already set
1211 if (currentValue
== styleName
)
1214 SetValue(styleName
);
1216 else if (!currentValue
.IsEmpty())
1217 SetValue(wxEmptyString
);