Added custom properties to style definitions and style sheets
[wxWidgets.git] / src / richtext / richtextstyles.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/richtext/richtextstyles.cpp
3 // Purpose: Style management for wxRichTextCtrl
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 2005-09-30
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #if wxUSE_RICHTEXT
20
21 #include "wx/richtext/richtextstyles.h"
22
23 #ifndef WX_PRECOMP
24 #include "wx/wx.h"
25 #endif
26
27 #include "wx/filename.h"
28 #include "wx/clipbrd.h"
29 #include "wx/wfstream.h"
30 #include "wx/settings.h"
31
32 #include "wx/richtext/richtextctrl.h"
33
34 IMPLEMENT_CLASS(wxRichTextStyleDefinition, wxObject)
35 IMPLEMENT_CLASS(wxRichTextCharacterStyleDefinition, wxRichTextStyleDefinition)
36 IMPLEMENT_CLASS(wxRichTextParagraphStyleDefinition, wxRichTextStyleDefinition)
37 IMPLEMENT_CLASS(wxRichTextListStyleDefinition, wxRichTextParagraphStyleDefinition)
38 IMPLEMENT_CLASS(wxRichTextBoxStyleDefinition, wxRichTextStyleDefinition)
39
40 /*!
41 * A definition
42 */
43
44 void wxRichTextStyleDefinition::Copy(const wxRichTextStyleDefinition& def)
45 {
46 m_name = def.m_name;
47 m_baseStyle = def.m_baseStyle;
48 m_style = def.m_style;
49 m_description = def.m_description;
50 m_properties = def.m_properties;
51 }
52
53 bool wxRichTextStyleDefinition::Eq(const wxRichTextStyleDefinition& def) const
54 {
55 return (m_name == def.m_name && m_baseStyle == def.m_baseStyle && m_style == def.m_style && m_properties == def.m_properties);
56 }
57
58 /// Gets the style combined with the base style
59 wxRichTextAttr wxRichTextStyleDefinition::GetStyleMergedWithBase(const wxRichTextStyleSheet* sheet) const
60 {
61 if (m_baseStyle.IsEmpty())
62 return m_style;
63
64 bool isParaStyle = IsKindOf(CLASSINFO(wxRichTextParagraphStyleDefinition));
65 bool isCharStyle = IsKindOf(CLASSINFO(wxRichTextCharacterStyleDefinition));
66 bool isListStyle = IsKindOf(CLASSINFO(wxRichTextListStyleDefinition));
67 bool isBoxStyle = IsKindOf(CLASSINFO(wxRichTextBoxStyleDefinition));
68
69 // Collect the styles, detecting loops
70 wxArrayString styleNames;
71 wxList styles;
72 const wxRichTextStyleDefinition* def = this;
73 while (def)
74 {
75 styles.Insert((wxObject*) def);
76 styleNames.Add(def->GetName());
77
78 wxString baseStyleName = def->GetBaseStyle();
79 if (!baseStyleName.IsEmpty() && styleNames.Index(baseStyleName) == wxNOT_FOUND)
80 {
81 if (isParaStyle)
82 def = sheet->FindParagraphStyle(baseStyleName);
83 else if (isCharStyle)
84 def = sheet->FindCharacterStyle(baseStyleName);
85 else if (isListStyle)
86 def = sheet->FindListStyle(baseStyleName);
87 else if (isBoxStyle)
88 def = sheet->FindBoxStyle(baseStyleName);
89 else
90 def = sheet->FindStyle(baseStyleName);
91 }
92 else
93 def = NULL;
94 }
95
96 wxRichTextAttr attr;
97 wxList::compatibility_iterator node = styles.GetFirst();
98 while (node)
99 {
100 wxRichTextStyleDefinition* def = (wxRichTextStyleDefinition*) node->GetData();
101 attr.Apply(def->GetStyle(), NULL);
102 node = node->GetNext();
103 }
104
105 return attr;
106 }
107
108 /*!
109 * Paragraph style definition
110 */
111
112 void wxRichTextParagraphStyleDefinition::Copy(const wxRichTextParagraphStyleDefinition& def)
113 {
114 wxRichTextStyleDefinition::Copy(def);
115
116 m_nextStyle = def.m_nextStyle;
117 }
118
119 bool wxRichTextParagraphStyleDefinition::operator ==(const wxRichTextParagraphStyleDefinition& def) const
120 {
121 return (Eq(def) && m_nextStyle == def.m_nextStyle);
122 }
123
124 /*!
125 * Box style definition
126 */
127
128 void wxRichTextBoxStyleDefinition::Copy(const wxRichTextBoxStyleDefinition& def)
129 {
130 wxRichTextStyleDefinition::Copy(def);
131 }
132
133 bool wxRichTextBoxStyleDefinition::operator ==(const wxRichTextBoxStyleDefinition& def) const
134 {
135 return (Eq(def));
136 }
137
138 /*!
139 * List style definition
140 */
141
142 void wxRichTextListStyleDefinition::Copy(const wxRichTextListStyleDefinition& def)
143 {
144 wxRichTextParagraphStyleDefinition::Copy(def);
145
146 int i;
147 for (i = 0; i < 10; i++)
148 m_levelStyles[i] = def.m_levelStyles[i];
149 }
150
151 bool wxRichTextListStyleDefinition::operator ==(const wxRichTextListStyleDefinition& def) const
152 {
153 if (!Eq(def))
154 return false;
155 int i;
156 for (i = 0; i < 10; i++)
157 if (!(m_levelStyles[i] == def.m_levelStyles[i]))
158 return false;
159
160 return true;
161 }
162
163 /// Sets/gets the attributes for the given level
164 void wxRichTextListStyleDefinition::SetLevelAttributes(int i, const wxRichTextAttr& attr)
165 {
166 wxASSERT( (i >= 0 && i < 10) );
167 if (i >= 0 && i < 10)
168 m_levelStyles[i] = attr;
169 }
170
171 const wxRichTextAttr* wxRichTextListStyleDefinition::GetLevelAttributes(int i) const
172 {
173 wxASSERT( (i >= 0 && i < 10) );
174 if (i >= 0 && i < 10)
175 return & m_levelStyles[i];
176 else
177 return NULL;
178 }
179
180 wxRichTextAttr* wxRichTextListStyleDefinition::GetLevelAttributes(int i)
181 {
182 wxASSERT( (i >= 0 && i < 10) );
183 if (i >= 0 && i < 10)
184 return & m_levelStyles[i];
185 else
186 return NULL;
187 }
188
189 /// Convenience function for setting the major attributes for a list level specification
190 void wxRichTextListStyleDefinition::SetAttributes(int i, int leftIndent, int leftSubIndent, int bulletStyle, const wxString& bulletSymbol)
191 {
192 wxASSERT( (i >= 0 && i < 10) );
193 if (i >= 0 && i < 10)
194 {
195 wxRichTextAttr attr;
196
197 attr.SetBulletStyle(bulletStyle);
198 attr.SetLeftIndent(leftIndent, leftSubIndent);
199
200 if (!bulletSymbol.IsEmpty())
201 {
202 if (bulletStyle & wxTEXT_ATTR_BULLET_STYLE_SYMBOL)
203 attr.SetBulletText(bulletSymbol);
204 else
205 attr.SetBulletName(bulletSymbol);
206 }
207
208 m_levelStyles[i] = attr;
209 }
210 }
211
212 /// Finds the level corresponding to the given indentation
213 int wxRichTextListStyleDefinition::FindLevelForIndent(int indent) const
214 {
215 int i;
216 for (i = 0; i < 10; i++)
217 {
218 if (indent < m_levelStyles[i].GetLeftIndent())
219 {
220 if (i > 0)
221 return i - 1;
222 else
223 return 0;
224 }
225 }
226 return 9;
227 }
228
229 /// Combine the list style with a paragraph style, using the given indent (from which
230 /// an appropriate level is found)
231 wxRichTextAttr wxRichTextListStyleDefinition::CombineWithParagraphStyle(int indent, const wxRichTextAttr& paraStyle, wxRichTextStyleSheet* styleSheet)
232 {
233 int listLevel = FindLevelForIndent(indent);
234
235 wxRichTextAttr attr(*GetLevelAttributes(listLevel));
236 int oldLeftIndent = attr.GetLeftIndent();
237 int oldLeftSubIndent = attr.GetLeftSubIndent();
238
239 // First apply the overall paragraph style, if any
240 if (styleSheet)
241 attr.Apply(GetStyleMergedWithBase(styleSheet));
242 else
243 attr.Apply(GetStyle());
244
245 // Then apply paragraph style, e.g. from paragraph style definition
246 attr.Apply(paraStyle);
247
248 // We override the indents according to the list definition
249 attr.SetLeftIndent(oldLeftIndent, oldLeftSubIndent);
250
251 return attr;
252 }
253
254 /// Combine the base and list style, using the given indent (from which
255 /// an appropriate level is found)
256 wxRichTextAttr wxRichTextListStyleDefinition::GetCombinedStyle(int indent, wxRichTextStyleSheet* styleSheet)
257 {
258 int listLevel = FindLevelForIndent(indent);
259 return GetCombinedStyleForLevel(listLevel, styleSheet);
260 }
261
262 /// Combine the base and list style, using the given indent (from which
263 /// an appropriate level is found)
264 wxRichTextAttr wxRichTextListStyleDefinition::GetCombinedStyleForLevel(int listLevel, wxRichTextStyleSheet* styleSheet)
265 {
266 wxRichTextAttr attr(*GetLevelAttributes(listLevel));
267 int oldLeftIndent = attr.GetLeftIndent();
268 int oldLeftSubIndent = attr.GetLeftSubIndent();
269
270 // Apply the overall paragraph style, if any
271 if (styleSheet)
272 attr.Apply(GetStyleMergedWithBase(styleSheet));
273 else
274 attr.Apply(GetStyle());
275
276 // We override the indents according to the list definition
277 attr.SetLeftIndent(oldLeftIndent, oldLeftSubIndent);
278
279 return attr;
280 }
281
282 /// Is this a numbered list?
283 bool wxRichTextListStyleDefinition::IsNumbered(int i) const
284 {
285 return (0 != (GetLevelAttributes(i)->GetFlags() &
286 (wxTEXT_ATTR_BULLET_STYLE_ARABIC|wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER|wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER|
287 wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER|wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER)));
288 }
289
290 /*!
291 * The style manager
292 */
293
294 IMPLEMENT_CLASS(wxRichTextStyleSheet, wxObject)
295
296 wxRichTextStyleSheet::~wxRichTextStyleSheet()
297 {
298 DeleteStyles();
299
300 if (m_nextSheet)
301 m_nextSheet->m_previousSheet = m_previousSheet;
302
303 if (m_previousSheet)
304 m_previousSheet->m_nextSheet = m_nextSheet;
305
306 m_previousSheet = NULL;
307 m_nextSheet = NULL;
308 }
309
310 /// Initialisation
311 void wxRichTextStyleSheet::Init()
312 {
313 m_previousSheet = NULL;
314 m_nextSheet = NULL;
315 }
316
317 /// Add a definition to one of the style lists
318 bool wxRichTextStyleSheet::AddStyle(wxList& list, wxRichTextStyleDefinition* def)
319 {
320 if (!list.Find(def))
321 list.Append(def);
322 return true;
323 }
324
325 /// Remove a style
326 bool wxRichTextStyleSheet::RemoveStyle(wxList& list, wxRichTextStyleDefinition* def, bool deleteStyle)
327 {
328 wxList::compatibility_iterator node = list.Find(def);
329 if (node)
330 {
331 wxRichTextStyleDefinition* def = (wxRichTextStyleDefinition*) node->GetData();
332 list.Erase(node);
333 if (deleteStyle)
334 delete def;
335 return true;
336 }
337 else
338 return false;
339 }
340
341 /// Remove a style
342 bool wxRichTextStyleSheet::RemoveStyle(wxRichTextStyleDefinition* def, bool deleteStyle)
343 {
344 if (RemoveParagraphStyle(def, deleteStyle))
345 return true;
346 if (RemoveCharacterStyle(def, deleteStyle))
347 return true;
348 if (RemoveListStyle(def, deleteStyle))
349 return true;
350 if (RemoveBoxStyle(def, deleteStyle))
351 return true;
352 return false;
353 }
354
355 /// Find a definition by name
356 wxRichTextStyleDefinition* wxRichTextStyleSheet::FindStyle(const wxList& list, const wxString& name, bool recurse) const
357 {
358 for (wxList::compatibility_iterator node = list.GetFirst(); node; node = node->GetNext())
359 {
360 wxRichTextStyleDefinition* def = (wxRichTextStyleDefinition*) node->GetData();
361 if (def->GetName() == name)
362 return def;
363 }
364
365 if (m_nextSheet && recurse)
366 return m_nextSheet->FindStyle(list, name, recurse);
367
368 return NULL;
369 }
370
371 /// Delete all styles
372 void wxRichTextStyleSheet::DeleteStyles()
373 {
374 WX_CLEAR_LIST(wxList, m_characterStyleDefinitions);
375 WX_CLEAR_LIST(wxList, m_paragraphStyleDefinitions);
376 WX_CLEAR_LIST(wxList, m_listStyleDefinitions);
377 WX_CLEAR_LIST(wxList, m_boxStyleDefinitions);
378 }
379
380 /// Insert into list of style sheets
381 bool wxRichTextStyleSheet::InsertSheet(wxRichTextStyleSheet* before)
382 {
383 m_previousSheet = before->m_previousSheet;
384 m_nextSheet = before;
385
386 before->m_previousSheet = this;
387 return true;
388 }
389
390 /// Append to list of style sheets
391 bool wxRichTextStyleSheet::AppendSheet(wxRichTextStyleSheet* after)
392 {
393 wxRichTextStyleSheet* last = after;
394 while (last && last->m_nextSheet)
395 {
396 last = last->m_nextSheet;
397 }
398
399 if (last)
400 {
401 m_previousSheet = last;
402 last->m_nextSheet = this;
403
404 return true;
405 }
406 else
407 return false;
408 }
409
410 /// Unlink from the list of style sheets
411 void wxRichTextStyleSheet::Unlink()
412 {
413 if (m_previousSheet)
414 m_previousSheet->m_nextSheet = m_nextSheet;
415 if (m_nextSheet)
416 m_nextSheet->m_previousSheet = m_previousSheet;
417
418 m_previousSheet = NULL;
419 m_nextSheet = NULL;
420 }
421
422 /// Add a definition to the character style list
423 bool wxRichTextStyleSheet::AddCharacterStyle(wxRichTextCharacterStyleDefinition* def)
424 {
425 def->GetStyle().SetCharacterStyleName(def->GetName());
426 return AddStyle(m_characterStyleDefinitions, def);
427 }
428
429 /// Add a definition to the paragraph style list
430 bool wxRichTextStyleSheet::AddParagraphStyle(wxRichTextParagraphStyleDefinition* def)
431 {
432 def->GetStyle().SetParagraphStyleName(def->GetName());
433 return AddStyle(m_paragraphStyleDefinitions, def);
434 }
435
436 /// Add a definition to the list style list
437 bool wxRichTextStyleSheet::AddListStyle(wxRichTextListStyleDefinition* def)
438 {
439 def->GetStyle().SetListStyleName(def->GetName());
440 return AddStyle(m_listStyleDefinitions, def);
441 }
442
443 /// Add a definition to the box style list
444 bool wxRichTextStyleSheet::AddBoxStyle(wxRichTextBoxStyleDefinition* def)
445 {
446 def->GetStyle().GetTextBoxAttr().SetBoxStyleName(def->GetName());
447 return AddStyle(m_boxStyleDefinitions, def);
448 }
449
450 /// Add a definition to the appropriate style list
451 bool wxRichTextStyleSheet::AddStyle(wxRichTextStyleDefinition* def)
452 {
453 wxRichTextListStyleDefinition* listDef = wxDynamicCast(def, wxRichTextListStyleDefinition);
454 if (listDef)
455 return AddListStyle(listDef);
456
457 wxRichTextParagraphStyleDefinition* paraDef = wxDynamicCast(def, wxRichTextParagraphStyleDefinition);
458 if (paraDef)
459 return AddParagraphStyle(paraDef);
460
461 wxRichTextCharacterStyleDefinition* charDef = wxDynamicCast(def, wxRichTextCharacterStyleDefinition);
462 if (charDef)
463 return AddCharacterStyle(charDef);
464
465 wxRichTextBoxStyleDefinition* boxDef = wxDynamicCast(def, wxRichTextBoxStyleDefinition);
466 if (boxDef)
467 return AddBoxStyle(boxDef);
468
469 return false;
470 }
471
472 /// Find any definition by name
473 wxRichTextStyleDefinition* wxRichTextStyleSheet::FindStyle(const wxString& name, bool recurse) const
474 {
475 wxRichTextListStyleDefinition* listDef = FindListStyle(name, recurse);
476 if (listDef)
477 return listDef;
478
479 wxRichTextParagraphStyleDefinition* paraDef = FindParagraphStyle(name, recurse);
480 if (paraDef)
481 return paraDef;
482
483 wxRichTextCharacterStyleDefinition* charDef = FindCharacterStyle(name, recurse);
484 if (charDef)
485 return charDef;
486
487 wxRichTextBoxStyleDefinition* boxDef = FindBoxStyle(name, recurse);
488 if (boxDef)
489 return boxDef;
490
491 return NULL;
492 }
493
494 /// Copy
495 void wxRichTextStyleSheet::Copy(const wxRichTextStyleSheet& sheet)
496 {
497 DeleteStyles();
498
499 wxList::compatibility_iterator node;
500
501 for (node = sheet.m_characterStyleDefinitions.GetFirst(); node; node = node->GetNext())
502 {
503 wxRichTextCharacterStyleDefinition* def = (wxRichTextCharacterStyleDefinition*) node->GetData();
504 AddCharacterStyle(new wxRichTextCharacterStyleDefinition(*def));
505 }
506
507 for (node = sheet.m_paragraphStyleDefinitions.GetFirst(); node; node = node->GetNext())
508 {
509 wxRichTextParagraphStyleDefinition* def = (wxRichTextParagraphStyleDefinition*) node->GetData();
510 AddParagraphStyle(new wxRichTextParagraphStyleDefinition(*def));
511 }
512
513 for (node = sheet.m_listStyleDefinitions.GetFirst(); node; node = node->GetNext())
514 {
515 wxRichTextListStyleDefinition* def = (wxRichTextListStyleDefinition*) node->GetData();
516 AddListStyle(new wxRichTextListStyleDefinition(*def));
517 }
518
519 for (node = sheet.m_boxStyleDefinitions.GetFirst(); node; node = node->GetNext())
520 {
521 wxRichTextBoxStyleDefinition* def = (wxRichTextBoxStyleDefinition*) node->GetData();
522 AddBoxStyle(new wxRichTextBoxStyleDefinition(*def));
523 }
524
525 SetName(sheet.GetName());
526 SetDescription(sheet.GetDescription());
527 m_properties = sheet.m_properties;
528 }
529
530 /// Equality
531 bool wxRichTextStyleSheet::operator==(const wxRichTextStyleSheet& WXUNUSED(sheet)) const
532 {
533 // TODO
534 return false;
535 }
536
537
538 #if wxUSE_HTML
539
540 // Functions for dealing with clashing names for different kinds of style.
541 // Returns "P", "C", "L" or "B" (paragraph, character, list or box) for
542 // style name | type.
543 static wxString wxGetRichTextStyleType(const wxString& style)
544 {
545 return style.AfterLast(wxT('|'));
546 }
547
548 static wxString wxGetRichTextStyle(const wxString& style)
549 {
550 return style.BeforeLast(wxT('|'));
551 }
552
553
554 /*!
555 * wxRichTextStyleListBox: a listbox to display styles.
556 */
557
558 IMPLEMENT_CLASS(wxRichTextStyleListBox, wxHtmlListBox)
559
560 BEGIN_EVENT_TABLE(wxRichTextStyleListBox, wxHtmlListBox)
561 EVT_LEFT_DOWN(wxRichTextStyleListBox::OnLeftDown)
562 EVT_LEFT_DCLICK(wxRichTextStyleListBox::OnLeftDoubleClick)
563 EVT_IDLE(wxRichTextStyleListBox::OnIdle)
564 END_EVENT_TABLE()
565
566 wxRichTextStyleListBox::wxRichTextStyleListBox(wxWindow* parent, wxWindowID id, const wxPoint& pos,
567 const wxSize& size, long style)
568 {
569 Init();
570 Create(parent, id, pos, size, style);
571 }
572
573 bool wxRichTextStyleListBox::Create(wxWindow* parent, wxWindowID id, const wxPoint& pos,
574 const wxSize& size, long style)
575 {
576 return wxHtmlListBox::Create(parent, id, pos, size, style);
577 }
578
579 wxRichTextStyleListBox::~wxRichTextStyleListBox()
580 {
581 }
582
583 /// Returns the HTML for this item
584 wxString wxRichTextStyleListBox::OnGetItem(size_t n) const
585 {
586 if (!GetStyleSheet())
587 return wxEmptyString;
588
589 wxRichTextStyleDefinition* def = GetStyle(n);
590 if (def)
591 return CreateHTML(def);
592
593 return wxEmptyString;
594 }
595
596 // Get style for index
597 wxRichTextStyleDefinition* wxRichTextStyleListBox::GetStyle(size_t i) const
598 {
599 if (!GetStyleSheet())
600 return NULL;
601
602 if (i >= m_styleNames.GetCount() /* || i < 0 */ )
603 return NULL;
604
605 wxString styleType = wxGetRichTextStyleType(m_styleNames[i]);
606 wxString style = wxGetRichTextStyle(m_styleNames[i]);
607 if (styleType == wxT("P"))
608 return GetStyleSheet()->FindParagraphStyle(style);
609 else if (styleType == wxT("C"))
610 return GetStyleSheet()->FindCharacterStyle(style);
611 else if (styleType == wxT("L"))
612 return GetStyleSheet()->FindListStyle(style);
613 else if (styleType == wxT("B"))
614 return GetStyleSheet()->FindBoxStyle(style);
615 else
616 return GetStyleSheet()->FindStyle(style);
617 }
618
619 /// Updates the list
620 void wxRichTextStyleListBox::UpdateStyles()
621 {
622 if (GetStyleSheet())
623 {
624 int oldSel = GetSelection();
625
626 SetSelection(wxNOT_FOUND);
627
628 m_styleNames.Clear();
629
630 size_t i;
631 if (GetStyleType() == wxRICHTEXT_STYLE_ALL || GetStyleType() == wxRICHTEXT_STYLE_PARAGRAPH)
632 {
633 for (i = 0; i < GetStyleSheet()->GetParagraphStyleCount(); i++)
634 m_styleNames.Add(GetStyleSheet()->GetParagraphStyle(i)->GetName() + wxT("|P"));
635 }
636 if (GetStyleType() == wxRICHTEXT_STYLE_ALL || GetStyleType() == wxRICHTEXT_STYLE_CHARACTER)
637 {
638 for (i = 0; i < GetStyleSheet()->GetCharacterStyleCount(); i++)
639 m_styleNames.Add(GetStyleSheet()->GetCharacterStyle(i)->GetName() + wxT("|C"));
640 }
641 if (GetStyleType() == wxRICHTEXT_STYLE_ALL || GetStyleType() == wxRICHTEXT_STYLE_LIST)
642 {
643 for (i = 0; i < GetStyleSheet()->GetListStyleCount(); i++)
644 m_styleNames.Add(GetStyleSheet()->GetListStyle(i)->GetName() + wxT("|L"));
645 }
646 if (GetStyleType() == wxRICHTEXT_STYLE_ALL || GetStyleType() == wxRICHTEXT_STYLE_BOX)
647 {
648 for (i = 0; i < GetStyleSheet()->GetBoxStyleCount(); i++)
649 m_styleNames.Add(GetStyleSheet()->GetBoxStyle(i)->GetName() + wxT("|B"));
650 }
651
652 m_styleNames.Sort();
653 SetItemCount(m_styleNames.GetCount());
654
655 Refresh();
656
657 int newSel = -1;
658 if (oldSel >= 0 && oldSel < (int) GetItemCount())
659 newSel = oldSel;
660 else if (GetItemCount() > 0)
661 newSel = 0;
662
663 if (newSel >= 0)
664 {
665 SetSelection(newSel);
666 SendSelectedEvent();
667 }
668 }
669 }
670
671 // Get index for style name
672 int wxRichTextStyleListBox::GetIndexForStyle(const wxString& name) const
673 {
674 wxString s(name);
675 if (GetStyleType() == wxRICHTEXT_STYLE_PARAGRAPH)
676 s += wxT("|P");
677 else if (GetStyleType() == wxRICHTEXT_STYLE_CHARACTER)
678 s += wxT("|C");
679 else if (GetStyleType() == wxRICHTEXT_STYLE_LIST)
680 s += wxT("|L");
681 else if (GetStyleType() == wxRICHTEXT_STYLE_BOX)
682 s += wxT("|B");
683 else
684 {
685 if (m_styleNames.Index(s + wxT("|P")) != wxNOT_FOUND)
686 s += wxT("|P");
687 else if (m_styleNames.Index(s + wxT("|C")) != wxNOT_FOUND)
688 s += wxT("|C");
689 else if (m_styleNames.Index(s + wxT("|L")) != wxNOT_FOUND)
690 s += wxT("|L");
691 else if (m_styleNames.Index(s + wxT("|B")) != wxNOT_FOUND)
692 s += wxT("|B");
693 }
694 return m_styleNames.Index(s);
695 }
696
697 /// Set selection for string
698 int wxRichTextStyleListBox::SetStyleSelection(const wxString& name)
699 {
700 int i = GetIndexForStyle(name);
701 if (i > -1)
702 SetSelection(i);
703 return i;
704 }
705
706 // Convert a colour to a 6-digit hex string
707 static wxString ColourToHexString(const wxColour& col)
708 {
709 wxString hex;
710
711 hex += wxDecToHex(col.Red());
712 hex += wxDecToHex(col.Green());
713 hex += wxDecToHex(col.Blue());
714
715 return hex;
716 }
717
718 /// Creates a suitable HTML fragment for a definition
719 wxString wxRichTextStyleListBox::CreateHTML(wxRichTextStyleDefinition* def) const
720 {
721 // TODO: indicate list format for list style types
722
723 wxString str;
724
725 bool isCentred = false;
726
727 wxRichTextAttr attr(def->GetStyleMergedWithBase(GetStyleSheet()));
728
729 if (attr.HasAlignment() && attr.GetAlignment() == wxTEXT_ALIGNMENT_CENTRE)
730 isCentred = true;
731
732 if (isCentred)
733 str << wxT("<center>");
734
735
736 str << wxT("<table><tr>");
737
738 if (attr.GetLeftIndent() > 0)
739 {
740 wxClientDC dc((wxWindow*) this);
741
742 str << wxT("<td width=") << wxMin(50, (ConvertTenthsMMToPixels(dc, attr.GetLeftIndent())/2)) << wxT("></td>");
743 }
744
745 if (isCentred)
746 str << wxT("<td nowrap align=\"center\">");
747 else
748 str << wxT("<td nowrap>");
749
750 #ifdef __WXMSW__
751 int size = 2;
752 #else
753 int size = 3;
754 #endif
755
756 // Guess a standard font size
757 int stdFontSize = 0;
758
759 // First see if we have a default/normal style to base the size on
760 wxString normalTranslated(_("normal"));
761 wxString defaultTranslated(_("default"));
762 size_t i;
763 for (i = 0; i < GetStyleSheet()->GetParagraphStyleCount(); i++)
764 {
765 wxRichTextStyleDefinition* d = GetStyleSheet()->GetParagraphStyle(i);
766 wxString name = d->GetName().Lower();
767 if (name.Find(wxT("normal")) != wxNOT_FOUND || name.Find(normalTranslated) != wxNOT_FOUND ||
768 name.Find(wxT("default")) != wxNOT_FOUND || name.Find(defaultTranslated) != wxNOT_FOUND)
769 {
770 wxRichTextAttr attr2(d->GetStyleMergedWithBase(GetStyleSheet()));
771 if (attr2.HasFontSize())
772 {
773 stdFontSize = attr2.GetFontSize();
774 break;
775 }
776 }
777 }
778
779 if (stdFontSize == 0)
780 {
781 // Look at sizes up to 20 points, and see which is the most common
782 wxArrayInt sizes;
783 size_t maxSize = 20;
784 for (i = 0; i <= maxSize; i++)
785 sizes.Add(0);
786 for (i = 0; i < m_styleNames.GetCount(); i++)
787 {
788 wxRichTextStyleDefinition* d = GetStyle(i);
789 if (d)
790 {
791 wxRichTextAttr attr2(d->GetStyleMergedWithBase(GetStyleSheet()));
792 if (attr2.HasFontSize())
793 {
794 if (attr2.GetFontSize() <= (int) maxSize)
795 sizes[attr2.GetFontSize()] ++;
796 }
797 }
798 }
799 int mostCommonSize = 0;
800 for (i = 0; i <= maxSize; i++)
801 {
802 if (sizes[i] > mostCommonSize)
803 mostCommonSize = i;
804 }
805 if (mostCommonSize > 0)
806 stdFontSize = mostCommonSize;
807 }
808
809 if (stdFontSize == 0)
810 stdFontSize = 12;
811
812 int thisFontSize = ((attr.GetFlags() & wxTEXT_ATTR_FONT_SIZE) != 0) ? attr.GetFontSize() : stdFontSize;
813
814 if (thisFontSize < stdFontSize)
815 size --;
816 else if (thisFontSize > stdFontSize)
817 size ++;
818
819 str += wxT("<font");
820
821 str << wxT(" size=") << size;
822
823 if (!attr.GetFontFaceName().IsEmpty())
824 str << wxT(" face=\"") << attr.GetFontFaceName() << wxT("\"");
825
826 if (attr.GetTextColour().IsOk())
827 str << wxT(" color=\"#") << ColourToHexString(attr.GetTextColour()) << wxT("\"");
828
829 str << wxT(">");
830
831 bool hasBold = false;
832 bool hasItalic = false;
833 bool hasUnderline = false;
834
835 if (attr.GetFontWeight() == wxBOLD)
836 hasBold = true;
837 if (attr.GetFontStyle() == wxITALIC)
838 hasItalic = true;
839 if (attr.GetFontUnderlined())
840 hasUnderline = true;
841
842 if (hasBold)
843 str << wxT("<b>");
844 if (hasItalic)
845 str << wxT("<i>");
846 if (hasUnderline)
847 str << wxT("<u>");
848
849 str += def->GetName();
850
851 if (hasUnderline)
852 str << wxT("</u>");
853 if (hasItalic)
854 str << wxT("</i>");
855 if (hasBold)
856 str << wxT("</b>");
857
858 if (isCentred)
859 str << wxT("</centre>");
860
861 str << wxT("</font>");
862
863 str << wxT("</td></tr></table>");
864
865 if (isCentred)
866 str << wxT("</center>");
867
868 return str;
869 }
870
871 // Convert units in tends of a millimetre to device units
872 int wxRichTextStyleListBox::ConvertTenthsMMToPixels(wxDC& dc, int units) const
873 {
874 int ppi = dc.GetPPI().x;
875
876 // There are ppi pixels in 254.1 "1/10 mm"
877
878 double pixels = ((double) units * (double)ppi) / 254.1;
879
880 return (int) pixels;
881 }
882
883 void wxRichTextStyleListBox::OnLeftDown(wxMouseEvent& event)
884 {
885 wxVListBox::OnLeftDown(event);
886
887 int item = VirtualHitTest(event.GetPosition().y);
888 if (item != wxNOT_FOUND && GetApplyOnSelection())
889 ApplyStyle(item);
890 }
891
892 void wxRichTextStyleListBox::OnLeftDoubleClick(wxMouseEvent& event)
893 {
894 wxVListBox::OnLeftDown(event);
895
896 int item = VirtualHitTest(event.GetPosition().y);
897 if (item != wxNOT_FOUND && !GetApplyOnSelection())
898 ApplyStyle(item);
899 }
900
901 /// Helper for listbox and combo control
902 wxString wxRichTextStyleListBox::GetStyleToShowInIdleTime(wxRichTextCtrl* ctrl, wxRichTextStyleType styleType)
903 {
904 int adjustedCaretPos = ctrl->GetAdjustedCaretPosition(ctrl->GetCaretPosition());
905
906 wxString styleName;
907
908 wxRichTextAttr attr;
909 ctrl->GetStyle(adjustedCaretPos, attr);
910
911 // Take into account current default style just chosen by user
912 if (ctrl->IsDefaultStyleShowing())
913 {
914 wxRichTextApplyStyle(attr, ctrl->GetDefaultStyleEx());
915
916 if ((styleType == wxRICHTEXT_STYLE_ALL || styleType == wxRICHTEXT_STYLE_CHARACTER) &&
917 !attr.GetCharacterStyleName().IsEmpty())
918 styleName = attr.GetCharacterStyleName();
919 else if ((styleType == wxRICHTEXT_STYLE_ALL || styleType == wxRICHTEXT_STYLE_PARAGRAPH) &&
920 !attr.GetParagraphStyleName().IsEmpty())
921 styleName = attr.GetParagraphStyleName();
922 else if ((styleType == wxRICHTEXT_STYLE_ALL || styleType == wxRICHTEXT_STYLE_LIST) &&
923 !attr.GetListStyleName().IsEmpty())
924 styleName = attr.GetListStyleName();
925 // TODO: when we have a concept of focused object (text box), we'll
926 // use the paragraph style name of the focused object as the frame style name.
927 #if 0
928 else if ((styleType == wxRICHTEXT_STYLE_ALL || styleType == wxRICHTEXT_STYLE_BOX) &&
929 !attr.GetBoxStyleName().IsEmpty())
930 styleName = attr.GetBoxStyleName();
931 #endif
932 }
933 else if ((styleType == wxRICHTEXT_STYLE_ALL || styleType == wxRICHTEXT_STYLE_CHARACTER) &&
934 !attr.GetCharacterStyleName().IsEmpty())
935 {
936 styleName = attr.GetCharacterStyleName();
937 }
938 else if ((styleType == wxRICHTEXT_STYLE_ALL || styleType == wxRICHTEXT_STYLE_PARAGRAPH) &&
939 !attr.GetParagraphStyleName().IsEmpty())
940 {
941 styleName = attr.GetParagraphStyleName();
942 }
943 else if ((styleType == wxRICHTEXT_STYLE_ALL || styleType == wxRICHTEXT_STYLE_LIST) &&
944 !attr.GetListStyleName().IsEmpty())
945 {
946 styleName = attr.GetListStyleName();
947 }
948
949 return styleName;
950 }
951
952 /// Auto-select from style under caret in idle time
953 void wxRichTextStyleListBox::OnIdle(wxIdleEvent& event)
954 {
955 if (CanAutoSetSelection() && GetRichTextCtrl() && IsShownOnScreen() && wxWindow::FindFocus() != this)
956 {
957 wxString styleName = GetStyleToShowInIdleTime(GetRichTextCtrl(), GetStyleType());
958
959 int sel = GetSelection();
960 if (!styleName.IsEmpty())
961 {
962 // Don't do the selection if it's already set
963 if (sel == GetIndexForStyle(styleName))
964 return;
965
966 SetStyleSelection(styleName);
967 }
968 else if (sel != -1)
969 SetSelection(-1);
970 }
971 event.Skip();
972 }
973
974 /// Do selection
975 void wxRichTextStyleListBox::ApplyStyle(int item)
976 {
977 if ( item != wxNOT_FOUND )
978 {
979 wxRichTextStyleDefinition* def = GetStyle(item);
980 if (def && GetRichTextCtrl())
981 {
982 GetRichTextCtrl()->ApplyStyle(def);
983 GetRichTextCtrl()->SetFocus();
984 }
985 }
986 }
987
988 /*!
989 * wxRichTextStyleListCtrl class: manages a listbox and a choice control to
990 * switch shown style types
991 */
992
993 IMPLEMENT_CLASS(wxRichTextStyleListCtrl, wxControl)
994
995 BEGIN_EVENT_TABLE(wxRichTextStyleListCtrl, wxControl)
996 EVT_CHOICE(wxID_ANY, wxRichTextStyleListCtrl::OnChooseType)
997 EVT_SIZE(wxRichTextStyleListCtrl::OnSize)
998 END_EVENT_TABLE()
999
1000 wxRichTextStyleListCtrl::wxRichTextStyleListCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos,
1001 const wxSize& size, long style)
1002 {
1003 Init();
1004 Create(parent, id, pos, size, style);
1005 }
1006
1007 bool wxRichTextStyleListCtrl::Create(wxWindow* parent, wxWindowID id, const wxPoint& pos,
1008 const wxSize& size, long style)
1009 {
1010 if ((style & wxBORDER_MASK) == wxBORDER_DEFAULT)
1011 style |= wxBORDER_THEME;
1012
1013 wxControl::Create(parent, id, pos, size, style);
1014
1015 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
1016 if (size != wxDefaultSize)
1017 SetInitialSize(size);
1018
1019 bool showSelector = ((style & wxRICHTEXTSTYLELIST_HIDE_TYPE_SELECTOR) == 0);
1020
1021 wxBorder listBoxStyle;
1022 if (showSelector)
1023 listBoxStyle = wxBORDER_THEME;
1024 else
1025 listBoxStyle = wxBORDER_NONE;
1026
1027 m_styleListBox = new wxRichTextStyleListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, listBoxStyle);
1028
1029 wxBoxSizer* boxSizer = new wxBoxSizer(wxVERTICAL);
1030
1031 if (showSelector)
1032 {
1033 wxArrayString choices;
1034 choices.Add(_("All styles"));
1035 choices.Add(_("Paragraph styles"));
1036 choices.Add(_("Character styles"));
1037 choices.Add(_("List styles"));
1038 choices.Add(_("Box styles"));
1039
1040 m_styleChoice = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, choices);
1041
1042 boxSizer->Add(m_styleListBox, 1, wxALL|wxEXPAND, 5);
1043 boxSizer->Add(m_styleChoice, 0, wxLEFT|wxRIGHT|wxBOTTOM|wxEXPAND, 5);
1044 }
1045 else
1046 {
1047 boxSizer->Add(m_styleListBox, 1, wxALL|wxEXPAND, 0);
1048 }
1049
1050 SetSizer(boxSizer);
1051 Layout();
1052
1053 m_dontUpdate = true;
1054
1055 if (m_styleChoice)
1056 {
1057 int i = StyleTypeToIndex(m_styleListBox->GetStyleType());
1058 m_styleChoice->SetSelection(i);
1059 }
1060
1061 m_dontUpdate = false;
1062
1063 return true;
1064 }
1065
1066 wxRichTextStyleListCtrl::~wxRichTextStyleListCtrl()
1067 {
1068
1069 }
1070
1071 /// React to style type choice
1072 void wxRichTextStyleListCtrl::OnChooseType(wxCommandEvent& event)
1073 {
1074 if (event.GetEventObject() != m_styleChoice)
1075 event.Skip();
1076 else
1077 {
1078 if (m_dontUpdate)
1079 return;
1080
1081 wxRichTextStyleListBox::wxRichTextStyleType styleType = StyleIndexToType(event.GetSelection());
1082 m_styleListBox->SetSelection(-1);
1083 m_styleListBox->SetStyleType(styleType);
1084 }
1085 }
1086
1087 /// Lay out the controls
1088 void wxRichTextStyleListCtrl::OnSize(wxSizeEvent& WXUNUSED(event))
1089 {
1090 if (GetAutoLayout())
1091 Layout();
1092 }
1093
1094 /// Get the choice index for style type
1095 int wxRichTextStyleListCtrl::StyleTypeToIndex(wxRichTextStyleListBox::wxRichTextStyleType styleType)
1096 {
1097 if (styleType == wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL)
1098 {
1099 return 0;
1100 }
1101 else if (styleType == wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH)
1102 {
1103 return 1;
1104 }
1105 else if (styleType == wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER)
1106 {
1107 return 2;
1108 }
1109 else if (styleType == wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST)
1110 {
1111 return 3;
1112 }
1113 else if (styleType == wxRichTextStyleListBox::wxRICHTEXT_STYLE_BOX)
1114 {
1115 return 4;
1116 }
1117 return 0;
1118 }
1119
1120 /// Get the style type for choice index
1121 wxRichTextStyleListBox::wxRichTextStyleType wxRichTextStyleListCtrl::StyleIndexToType(int i)
1122 {
1123 if (i == 1)
1124 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH;
1125 else if (i == 2)
1126 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER;
1127 else if (i == 3)
1128 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST;
1129 else if (i == 4)
1130 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_BOX;
1131
1132 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL;
1133 }
1134
1135 /// Associates the control with a style manager
1136 void wxRichTextStyleListCtrl::SetStyleSheet(wxRichTextStyleSheet* styleSheet)
1137 {
1138 if (m_styleListBox)
1139 m_styleListBox->SetStyleSheet(styleSheet);
1140 }
1141
1142 wxRichTextStyleSheet* wxRichTextStyleListCtrl::GetStyleSheet() const
1143 {
1144 if (m_styleListBox)
1145 return m_styleListBox->GetStyleSheet();
1146 else
1147 return NULL;
1148 }
1149
1150 /// Associates the control with a wxRichTextCtrl
1151 void wxRichTextStyleListCtrl::SetRichTextCtrl(wxRichTextCtrl* ctrl)
1152 {
1153 if (m_styleListBox)
1154 m_styleListBox->SetRichTextCtrl(ctrl);
1155 }
1156
1157 wxRichTextCtrl* wxRichTextStyleListCtrl::GetRichTextCtrl() const
1158 {
1159 if (m_styleListBox)
1160 return m_styleListBox->GetRichTextCtrl();
1161 else
1162 return NULL;
1163 }
1164
1165 /// Set/get the style type to display
1166 void wxRichTextStyleListCtrl::SetStyleType(wxRichTextStyleListBox::wxRichTextStyleType styleType)
1167 {
1168 if ( !m_styleListBox )
1169 return;
1170
1171 m_styleListBox->SetStyleType(styleType);
1172
1173 m_dontUpdate = true;
1174
1175 if (m_styleChoice)
1176 {
1177 int i = StyleTypeToIndex(m_styleListBox->GetStyleType());
1178 m_styleChoice->SetSelection(i);
1179 }
1180
1181 m_dontUpdate = false;
1182 }
1183
1184 wxRichTextStyleListBox::wxRichTextStyleType wxRichTextStyleListCtrl::GetStyleType() const
1185 {
1186 if (m_styleListBox)
1187 return m_styleListBox->GetStyleType();
1188 else
1189 return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL;
1190 }
1191
1192 /// Updates the style list box
1193 void wxRichTextStyleListCtrl::UpdateStyles()
1194 {
1195 if (m_styleListBox)
1196 m_styleListBox->UpdateStyles();
1197 }
1198
1199 #if wxUSE_COMBOCTRL
1200
1201 /*!
1202 * Style drop-down for a wxComboCtrl
1203 */
1204
1205
1206 BEGIN_EVENT_TABLE(wxRichTextStyleComboPopup, wxRichTextStyleListBox)
1207 EVT_MOTION(wxRichTextStyleComboPopup::OnMouseMove)
1208 EVT_LEFT_DOWN(wxRichTextStyleComboPopup::OnMouseClick)
1209 END_EVENT_TABLE()
1210
1211 bool wxRichTextStyleComboPopup::Create( wxWindow* parent )
1212 {
1213 int borderStyle = GetDefaultBorder();
1214 if (borderStyle == wxBORDER_SUNKEN || borderStyle == wxBORDER_NONE)
1215 borderStyle = wxBORDER_THEME;
1216
1217 return wxRichTextStyleListBox::Create(parent, wxID_ANY,
1218 wxPoint(0,0), wxDefaultSize,
1219 borderStyle);
1220 }
1221
1222 void wxRichTextStyleComboPopup::SetStringValue( const wxString& s )
1223 {
1224 m_value = SetStyleSelection(s);
1225 }
1226
1227 wxString wxRichTextStyleComboPopup::GetStringValue() const
1228 {
1229 int sel = m_value;
1230 if (sel > -1)
1231 {
1232 wxRichTextStyleDefinition* def = GetStyle(sel);
1233 if (def)
1234 return def->GetName();
1235 }
1236 return wxEmptyString;
1237 }
1238
1239 //
1240 // Popup event handlers
1241 //
1242
1243 // Mouse hot-tracking
1244 void wxRichTextStyleComboPopup::OnMouseMove(wxMouseEvent& event)
1245 {
1246 // Move selection to cursor if it is inside the popup
1247
1248 int itemHere = wxRichTextStyleListBox::VirtualHitTest(event.GetPosition().y);
1249 if ( itemHere >= 0 )
1250 {
1251 wxRichTextStyleListBox::SetSelection(itemHere);
1252 m_itemHere = itemHere;
1253 }
1254 event.Skip();
1255 }
1256
1257 // On mouse left, set the value and close the popup
1258 void wxRichTextStyleComboPopup::OnMouseClick(wxMouseEvent& WXUNUSED(event))
1259 {
1260 if (m_itemHere >= 0)
1261 m_value = m_itemHere;
1262
1263 // Ordering is important, so we don't dismiss this popup accidentally
1264 // by setting the focus elsewhere e.g. in ApplyStyle
1265 Dismiss();
1266
1267 if (m_itemHere >= 0)
1268 wxRichTextStyleListBox::ApplyStyle(m_itemHere);
1269 }
1270
1271 /*!
1272 * wxRichTextStyleComboCtrl
1273 * A combo for applying styles.
1274 */
1275
1276 IMPLEMENT_CLASS(wxRichTextStyleComboCtrl, wxComboCtrl)
1277
1278 BEGIN_EVENT_TABLE(wxRichTextStyleComboCtrl, wxComboCtrl)
1279 EVT_IDLE(wxRichTextStyleComboCtrl::OnIdle)
1280 END_EVENT_TABLE()
1281
1282 bool wxRichTextStyleComboCtrl::Create(wxWindow* parent, wxWindowID id, const wxPoint& pos,
1283 const wxSize& size, long style)
1284 {
1285 if (!wxComboCtrl::Create(parent, id, wxEmptyString, pos, size, style))
1286 return false;
1287
1288 SetPopupMaxHeight(400);
1289
1290 m_stylePopup = new wxRichTextStyleComboPopup;
1291
1292 SetPopupControl(m_stylePopup);
1293
1294 return true;
1295 }
1296
1297 /// Auto-select from style under caret in idle time
1298
1299 // TODO: must be able to show italic, bold, combinations
1300 // in style box. Do we have a concept of automatic, temporary
1301 // styles that are added whenever we wish to show a style
1302 // that doesn't exist already? E.g. "Bold, Italic, Underline".
1303 // Word seems to generate these things on the fly.
1304 // If there's a named style already, it uses e.g. Heading1 + Bold, Italic
1305 // If you unembolden text in a style that has bold, it uses the
1306 // term "Not bold".
1307 // TODO: order styles alphabetically. This means indexes can change,
1308 // so need a different way to specify selections, i.e. by name.
1309
1310 void wxRichTextStyleComboCtrl::OnIdle(wxIdleEvent& event)
1311 {
1312 event.Skip();
1313
1314 if ( !m_stylePopup )
1315 return;
1316
1317 wxRichTextCtrl * const richtext = GetRichTextCtrl();
1318 if ( !richtext )
1319 return;
1320
1321 if ( !IsPopupShown() && IsShownOnScreen() && wxWindow::FindFocus() != this )
1322 {
1323 wxString styleName =
1324 wxRichTextStyleListBox::GetStyleToShowInIdleTime(richtext, m_stylePopup->GetStyleType());
1325
1326 wxString currentValue = GetValue();
1327 if (!styleName.IsEmpty())
1328 {
1329 // Don't do the selection if it's already set
1330 if (currentValue == styleName)
1331 return;
1332
1333 SetValue(styleName);
1334 }
1335 else if (!currentValue.IsEmpty())
1336 SetValue(wxEmptyString);
1337 }
1338 }
1339
1340 #endif
1341 // wxUSE_COMBOCTRL
1342
1343 #endif
1344 // wxUSE_HTML
1345
1346 #endif
1347 // wxUSE_RICHTEXT