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 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 wxTextAttr
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 // Guess a standard font size
625 // First see if we have a default/normal style to base the size on
626 wxString
normalTranslated(_("normal"));
627 wxString
defaultTranslated(_("default"));
629 for (i
= 0; i
< m_styleNames
.GetCount(); i
++)
631 wxString name
= m_styleNames
[i
].Lower();
632 if (name
.Find(wxT("normal")) != wxNOT_FOUND
|| name
.Find(normalTranslated
) != wxNOT_FOUND
||
633 name
.Find(wxT("default")) != wxNOT_FOUND
|| name
.Find(defaultTranslated
) != wxNOT_FOUND
)
635 wxRichTextStyleDefinition
* d
= GetStyleSheet()->FindStyle(m_styleNames
[i
]);
638 wxRichTextAttr
attr2(d
->GetStyleMergedWithBase(GetStyleSheet()));
639 if (attr2
.HasFontSize())
641 stdFontSize
= attr2
.GetFontSize();
648 if (stdFontSize
== 0)
650 // Look at sizes up to 20 points, and see which is the most common
653 for (i
= 0; i
<= maxSize
; i
++)
655 for (i
= 0; i
< m_styleNames
.GetCount(); i
++)
657 wxRichTextStyleDefinition
* d
= GetStyleSheet()->FindStyle(m_styleNames
[i
]);
660 wxRichTextAttr
attr2(d
->GetStyleMergedWithBase(GetStyleSheet()));
661 if (attr2
.HasFontSize())
663 if (attr2
.GetFontSize() <= (int) maxSize
)
664 sizes
[attr2
.GetFontSize()] ++;
668 int mostCommonSize
= 0;
669 for (i
= 0; i
<= maxSize
; i
++)
671 if (sizes
[i
] > mostCommonSize
)
674 if (mostCommonSize
> 0)
675 stdFontSize
= mostCommonSize
;
678 if (stdFontSize
== 0)
681 int thisFontSize
= ((attr
.GetFlags() & wxTEXT_ATTR_FONT_SIZE
) != 0) ? attr
.GetFontSize() : stdFontSize
;
683 if (thisFontSize
< stdFontSize
)
685 else if (thisFontSize
> stdFontSize
)
690 str
<< wxT(" size=") << size
;
692 if (!attr
.GetFontFaceName().IsEmpty())
693 str
<< wxT(" face=\"") << attr
.GetFontFaceName() << wxT("\"");
695 if (attr
.GetTextColour().Ok())
696 str
<< wxT(" color=\"#") << ColourToHexString(attr
.GetTextColour()) << wxT("\"");
700 bool hasBold
= false;
701 bool hasItalic
= false;
702 bool hasUnderline
= false;
704 if (attr
.GetFontWeight() == wxBOLD
)
706 if (attr
.GetFontStyle() == wxITALIC
)
708 if (attr
.GetFontUnderlined())
718 str
+= def
->GetName();
728 str
<< wxT("</centre>");
730 str
<< wxT("</font>");
732 str
<< wxT("</td></tr></table>");
735 str
<< wxT("</center>");
740 // Convert units in tends of a millimetre to device units
741 int wxRichTextStyleListBox::ConvertTenthsMMToPixels(wxDC
& dc
, int units
) const
743 int ppi
= dc
.GetPPI().x
;
745 // There are ppi pixels in 254.1 "1/10 mm"
747 double pixels
= ((double) units
* (double)ppi
) / 254.1;
752 void wxRichTextStyleListBox::OnLeftDown(wxMouseEvent
& event
)
754 wxVListBox::OnLeftDown(event
);
756 int item
= HitTest(event
.GetPosition());
757 if (item
!= wxNOT_FOUND
&& GetApplyOnSelection())
761 void wxRichTextStyleListBox::OnLeftDoubleClick(wxMouseEvent
& event
)
763 wxVListBox::OnLeftDown(event
);
765 int item
= HitTest(event
.GetPosition());
766 if (item
!= wxNOT_FOUND
&& !GetApplyOnSelection())
770 /// Helper for listbox and combo control
771 wxString
wxRichTextStyleListBox::GetStyleToShowInIdleTime(wxRichTextCtrl
* ctrl
, wxRichTextStyleType styleType
)
773 int adjustedCaretPos
= ctrl
->GetAdjustedCaretPosition(ctrl
->GetCaretPosition());
778 ctrl
->GetStyle(adjustedCaretPos
, attr
);
780 // Take into account current default style just chosen by user
781 if (ctrl
->IsDefaultStyleShowing())
783 wxRichTextApplyStyle(attr
, ctrl
->GetDefaultStyleEx());
785 if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_CHARACTER
) &&
786 !attr
.GetCharacterStyleName().IsEmpty())
787 styleName
= attr
.GetCharacterStyleName();
788 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_PARAGRAPH
) &&
789 !attr
.GetParagraphStyleName().IsEmpty())
790 styleName
= attr
.GetParagraphStyleName();
791 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_LIST
) &&
792 !attr
.GetListStyleName().IsEmpty())
793 styleName
= attr
.GetListStyleName();
795 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_CHARACTER
) &&
796 !attr
.GetCharacterStyleName().IsEmpty())
798 styleName
= attr
.GetCharacterStyleName();
800 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_PARAGRAPH
) &&
801 !attr
.GetParagraphStyleName().IsEmpty())
803 styleName
= attr
.GetParagraphStyleName();
805 else if ((styleType
== wxRICHTEXT_STYLE_ALL
|| styleType
== wxRICHTEXT_STYLE_LIST
) &&
806 !attr
.GetListStyleName().IsEmpty())
808 styleName
= attr
.GetListStyleName();
814 /// Auto-select from style under caret in idle time
815 void wxRichTextStyleListBox::OnIdle(wxIdleEvent
& event
)
817 if (CanAutoSetSelection() && GetRichTextCtrl() && IsShownOnScreen() && wxWindow::FindFocus() != this)
819 wxString styleName
= GetStyleToShowInIdleTime(GetRichTextCtrl(), GetStyleType());
821 int sel
= GetSelection();
822 if (!styleName
.IsEmpty())
824 // Don't do the selection if it's already set
825 if (sel
== GetIndexForStyle(styleName
))
828 SetStyleSelection(styleName
);
837 void wxRichTextStyleListBox::ApplyStyle(int item
)
839 if ( item
!= wxNOT_FOUND
)
841 wxRichTextStyleDefinition
* def
= GetStyle(item
);
842 if (def
&& GetRichTextCtrl())
844 GetRichTextCtrl()->ApplyStyle(def
);
845 GetRichTextCtrl()->SetFocus();
851 * wxRichTextStyleListCtrl class: manages a listbox and a choice control to
852 * switch shown style types
855 IMPLEMENT_CLASS(wxRichTextStyleListCtrl
, wxControl
)
857 BEGIN_EVENT_TABLE(wxRichTextStyleListCtrl
, wxControl
)
858 EVT_CHOICE(wxID_ANY
, wxRichTextStyleListCtrl::OnChooseType
)
859 EVT_SIZE(wxRichTextStyleListCtrl::OnSize
)
862 wxRichTextStyleListCtrl::wxRichTextStyleListCtrl(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
863 const wxSize
& size
, long style
)
866 Create(parent
, id
, pos
, size
, style
);
869 bool wxRichTextStyleListCtrl::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
870 const wxSize
& size
, long style
)
872 if ((style
& wxBORDER_MASK
) == wxBORDER_DEFAULT
)
873 style
|= wxBORDER_THEME
;
875 wxControl::Create(parent
, id
, pos
, size
, style
);
877 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
));
878 if (size
!= wxDefaultSize
)
879 SetInitialSize(size
);
881 bool showSelector
= ((style
& wxRICHTEXTSTYLELIST_HIDE_TYPE_SELECTOR
) == 0);
883 wxBorder listBoxStyle
;
885 listBoxStyle
= wxBORDER_THEME
;
887 listBoxStyle
= wxBORDER_NONE
;
889 m_styleListBox
= new wxRichTextStyleListBox(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, listBoxStyle
);
891 wxBoxSizer
* boxSizer
= new wxBoxSizer(wxVERTICAL
);
895 wxArrayString choices
;
896 choices
.Add(_("All styles"));
897 choices
.Add(_("Paragraph styles"));
898 choices
.Add(_("Character styles"));
899 choices
.Add(_("List styles"));
901 m_styleChoice
= new wxChoice(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, choices
);
903 boxSizer
->Add(m_styleListBox
, 1, wxALL
|wxEXPAND
, 5);
904 boxSizer
->Add(m_styleChoice
, 0, wxLEFT
|wxRIGHT
|wxBOTTOM
|wxEXPAND
, 5);
908 boxSizer
->Add(m_styleListBox
, 1, wxALL
|wxEXPAND
, 0);
918 int i
= StyleTypeToIndex(m_styleListBox
->GetStyleType());
919 m_styleChoice
->SetSelection(i
);
922 m_dontUpdate
= false;
927 wxRichTextStyleListCtrl::~wxRichTextStyleListCtrl()
932 /// React to style type choice
933 void wxRichTextStyleListCtrl::OnChooseType(wxCommandEvent
& event
)
935 if (event
.GetEventObject() != m_styleChoice
)
942 wxRichTextStyleListBox::wxRichTextStyleType styleType
= StyleIndexToType(event
.GetSelection());
943 m_styleListBox
->SetStyleType(styleType
);
947 /// Lay out the controls
948 void wxRichTextStyleListCtrl::OnSize(wxSizeEvent
& WXUNUSED(event
))
954 /// Get the choice index for style type
955 int wxRichTextStyleListCtrl::StyleTypeToIndex(wxRichTextStyleListBox::wxRichTextStyleType styleType
)
957 if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
)
961 else if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH
)
965 else if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER
)
969 else if (styleType
== wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST
)
976 /// Get the style type for choice index
977 wxRichTextStyleListBox::wxRichTextStyleType
wxRichTextStyleListCtrl::StyleIndexToType(int i
)
980 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH
;
982 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER
;
984 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST
;
986 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
;
989 /// Associates the control with a style manager
990 void wxRichTextStyleListCtrl::SetStyleSheet(wxRichTextStyleSheet
* styleSheet
)
993 m_styleListBox
->SetStyleSheet(styleSheet
);
996 wxRichTextStyleSheet
* wxRichTextStyleListCtrl::GetStyleSheet() const
999 return m_styleListBox
->GetStyleSheet();
1004 /// Associates the control with a wxRichTextCtrl
1005 void wxRichTextStyleListCtrl::SetRichTextCtrl(wxRichTextCtrl
* ctrl
)
1008 m_styleListBox
->SetRichTextCtrl(ctrl
);
1011 wxRichTextCtrl
* wxRichTextStyleListCtrl::GetRichTextCtrl() const
1014 return m_styleListBox
->GetRichTextCtrl();
1019 /// Set/get the style type to display
1020 void wxRichTextStyleListCtrl::SetStyleType(wxRichTextStyleListBox::wxRichTextStyleType styleType
)
1022 if ( !m_styleListBox
)
1025 m_styleListBox
->SetStyleType(styleType
);
1027 m_dontUpdate
= true;
1031 int i
= StyleTypeToIndex(m_styleListBox
->GetStyleType());
1032 m_styleChoice
->SetSelection(i
);
1035 m_dontUpdate
= false;
1038 wxRichTextStyleListBox::wxRichTextStyleType
wxRichTextStyleListCtrl::GetStyleType() const
1041 return m_styleListBox
->GetStyleType();
1043 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL
;
1046 /// Updates the style list box
1047 void wxRichTextStyleListCtrl::UpdateStyles()
1050 m_styleListBox
->UpdateStyles();
1056 * Style drop-down for a wxComboCtrl
1060 BEGIN_EVENT_TABLE(wxRichTextStyleComboPopup
, wxRichTextStyleListBox
)
1061 EVT_MOTION(wxRichTextStyleComboPopup::OnMouseMove
)
1062 EVT_LEFT_DOWN(wxRichTextStyleComboPopup::OnMouseClick
)
1065 bool wxRichTextStyleComboPopup::Create( wxWindow
* parent
)
1067 int borderStyle
= GetDefaultBorder();
1068 if (borderStyle
== wxBORDER_SUNKEN
)
1069 borderStyle
= wxBORDER_SIMPLE
;
1071 return wxRichTextStyleListBox::Create(parent
, wxID_ANY
,
1072 wxPoint(0,0), wxDefaultSize
,
1076 void wxRichTextStyleComboPopup::SetStringValue( const wxString
& s
)
1078 m_value
= SetStyleSelection(s
);
1081 wxString
wxRichTextStyleComboPopup::GetStringValue() const
1086 wxRichTextStyleDefinition
* def
= GetStyle(sel
);
1088 return def
->GetName();
1090 return wxEmptyString
;
1094 // Popup event handlers
1097 // Mouse hot-tracking
1098 void wxRichTextStyleComboPopup::OnMouseMove(wxMouseEvent
& event
)
1100 // Move selection to cursor if it is inside the popup
1102 int itemHere
= wxRichTextStyleListBox::HitTest(event
.GetPosition());
1103 if ( itemHere
>= 0 )
1105 wxRichTextStyleListBox::SetSelection(itemHere
);
1106 m_itemHere
= itemHere
;
1111 // On mouse left, set the value and close the popup
1112 void wxRichTextStyleComboPopup::OnMouseClick(wxMouseEvent
& WXUNUSED(event
))
1114 if (m_itemHere
>= 0)
1115 m_value
= m_itemHere
;
1117 // Ordering is important, so we don't dismiss this popup accidentally
1118 // by setting the focus elsewhere e.g. in ApplyStyle
1121 if (m_itemHere
>= 0)
1122 wxRichTextStyleListBox::ApplyStyle(m_itemHere
);
1126 * wxRichTextStyleComboCtrl
1127 * A combo for applying styles.
1130 IMPLEMENT_CLASS(wxRichTextStyleComboCtrl
, wxComboCtrl
)
1132 BEGIN_EVENT_TABLE(wxRichTextStyleComboCtrl
, wxComboCtrl
)
1133 EVT_IDLE(wxRichTextStyleComboCtrl::OnIdle
)
1136 bool wxRichTextStyleComboCtrl::Create(wxWindow
* parent
, wxWindowID id
, const wxPoint
& pos
,
1137 const wxSize
& size
, long style
)
1139 if (!wxComboCtrl::Create(parent
, id
, wxEmptyString
, pos
, size
, style
))
1142 SetPopupMaxHeight(400);
1144 m_stylePopup
= new wxRichTextStyleComboPopup
;
1146 SetPopupControl(m_stylePopup
);
1151 /// Auto-select from style under caret in idle time
1153 // TODO: must be able to show italic, bold, combinations
1154 // in style box. Do we have a concept of automatic, temporary
1155 // styles that are added whenever we wish to show a style
1156 // that doesn't exist already? E.g. "Bold, Italic, Underline".
1157 // Word seems to generate these things on the fly.
1158 // If there's a named style already, it uses e.g. Heading1 + Bold, Italic
1159 // If you unembolden text in a style that has bold, it uses the
1161 // TODO: order styles alphabetically. This means indexes can change,
1162 // so need a different way to specify selections, i.e. by name.
1164 void wxRichTextStyleComboCtrl::OnIdle(wxIdleEvent
& event
)
1168 if ( !m_stylePopup
)
1171 wxRichTextCtrl
* const richtext
= GetRichTextCtrl();
1175 if ( !IsPopupShown() && IsShownOnScreen() && wxWindow::FindFocus() != this )
1177 wxString styleName
=
1178 wxRichTextStyleListBox::GetStyleToShowInIdleTime(richtext
, m_stylePopup
->GetStyleType());
1180 wxString currentValue
= GetValue();
1181 if (!styleName
.IsEmpty())
1183 // Don't do the selection if it's already set
1184 if (currentValue
== styleName
)
1187 SetValue(styleName
);
1189 else if (!currentValue
.IsEmpty())
1190 SetValue(wxEmptyString
);