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
)
1093 if ( !m_stylePopup
)
1096 wxRichTextCtrl
* const richtext
= GetRichTextCtrl();
1100 if ( !IsPopupShown() && wxWindow::FindFocus() != this )
1102 wxString styleName
=
1103 wxRichTextStyleListBox::GetStyleToShowInIdleTime(richtext
, m_stylePopup
->GetStyleType());
1105 wxString currentValue
= GetValue();
1106 if (!styleName
.IsEmpty())
1108 // Don't do the selection if it's already set
1109 if (currentValue
== styleName
)
1112 SetValue(styleName
);
1114 else if (!currentValue
.IsEmpty())
1115 SetValue(wxEmptyString
);