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