]> git.saurik.com Git - wxWidgets.git/blob - src/richtext/richtextstyles.cpp
fixed crash in <sub/sup> handling (bug #1545152)
[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/dcclient.h"
25 #endif
26
27 #include "wx/filename.h"
28 #include "wx/clipbrd.h"
29 #include "wx/wfstream.h"
30 #include "wx/module.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
38 /*!
39 * The style manager
40 */
41
42 IMPLEMENT_CLASS(wxRichTextStyleSheet, wxObject)
43
44 /// Initialisation
45 void wxRichTextStyleSheet::Init()
46 {
47 }
48
49 /// Add a definition to one of the style lists
50 bool wxRichTextStyleSheet::AddStyle(wxList& list, wxRichTextStyleDefinition* def)
51 {
52 if (!list.Find(def))
53 list.Append(def);
54 return true;
55 }
56
57 /// Remove a style
58 bool wxRichTextStyleSheet::RemoveStyle(wxList& list, wxRichTextStyleDefinition* def, bool deleteStyle)
59 {
60 wxList::compatibility_iterator node = list.Find(def);
61 if (node)
62 {
63 wxRichTextStyleDefinition* def = (wxRichTextStyleDefinition*) node->GetData();
64 list.Erase(node);
65 if (deleteStyle)
66 delete def;
67 return true;
68 }
69 else
70 return false;
71 }
72
73 /// Find a definition by name
74 wxRichTextStyleDefinition* wxRichTextStyleSheet::FindStyle(const wxList& list, const wxString& name) const
75 {
76 for (wxList::compatibility_iterator node = list.GetFirst(); node; node = node->GetNext())
77 {
78 wxRichTextStyleDefinition* def = (wxRichTextStyleDefinition*) node->GetData();
79 if (def->GetName().Lower() == name.Lower())
80 return def;
81 }
82 return NULL;
83 }
84
85 /// Delete all styles
86 void wxRichTextStyleSheet::DeleteStyles()
87 {
88 WX_CLEAR_LIST(wxList, m_characterStyleDefinitions);
89 WX_CLEAR_LIST(wxList, m_paragraphStyleDefinitions);
90 }
91
92 #if wxUSE_HTML
93 /*!
94 * wxRichTextStyleListBox class declaration
95 * A listbox to display styles.
96 */
97
98 IMPLEMENT_CLASS(wxRichTextStyleListBox, wxHtmlListBox)
99
100 BEGIN_EVENT_TABLE(wxRichTextStyleListBox, wxHtmlListBox)
101 EVT_LISTBOX(wxID_ANY, wxRichTextStyleListBox::OnSelect)
102 EVT_LEFT_DOWN(wxRichTextStyleListBox::OnLeftDown)
103 END_EVENT_TABLE()
104
105 wxRichTextStyleListBox::wxRichTextStyleListBox(wxWindow* parent, wxWindowID id, const wxPoint& pos,
106 const wxSize& size, long style): wxHtmlListBox(parent, id, pos, size, style)
107 {
108 m_styleSheet = NULL;
109 m_richTextCtrl = NULL;
110 }
111
112 wxRichTextStyleListBox::~wxRichTextStyleListBox()
113 {
114 }
115
116 /// Returns the HTML for this item
117 wxString wxRichTextStyleListBox::OnGetItem(size_t n) const
118 {
119 if (!GetStyleSheet())
120 return wxEmptyString;
121
122 // First paragraph styles, then character
123 if (n < GetStyleSheet()->GetParagraphStyleCount())
124 {
125 wxRichTextParagraphStyleDefinition* def = GetStyleSheet()->GetParagraphStyle(n);
126
127 wxString str = CreateHTML(def);
128 return str;
129 }
130
131 if ((n - GetStyleSheet()->GetParagraphStyleCount()) < GetStyleSheet()->GetCharacterStyleCount())
132 {
133 wxRichTextCharacterStyleDefinition* def = GetStyleSheet()->GetCharacterStyle(n - GetStyleSheet()->GetParagraphStyleCount());
134
135 wxString str = CreateHTML(def);
136 return str;
137 }
138 return wxEmptyString;
139 }
140
141 // Get style for index
142 wxRichTextStyleDefinition* wxRichTextStyleListBox::GetStyle(size_t i) const
143 {
144 if (!GetStyleSheet())
145 return NULL;
146
147 // First paragraph styles, then character
148 if (i < GetStyleSheet()->GetParagraphStyleCount())
149 return GetStyleSheet()->GetParagraphStyle(i);
150
151 if ((i - GetStyleSheet()->GetParagraphStyleCount()) < GetStyleSheet()->GetCharacterStyleCount())
152 return GetStyleSheet()->GetCharacterStyle(i - GetStyleSheet()->GetParagraphStyleCount());
153
154 return NULL;
155 }
156
157 /// Updates the list
158 void wxRichTextStyleListBox::UpdateStyles()
159 {
160 if (GetStyleSheet())
161 {
162 SetItemCount(GetStyleSheet()->GetParagraphStyleCount()+GetStyleSheet()->GetCharacterStyleCount());
163 Refresh();
164 }
165 }
166
167 // Convert a colour to a 6-digit hex string
168 static wxString ColourToHexString(const wxColour& col)
169 {
170 wxString hex;
171
172 hex += wxDecToHex(col.Red());
173 hex += wxDecToHex(col.Green());
174 hex += wxDecToHex(col.Blue());
175
176 return hex;
177 }
178
179 /// Creates a suitable HTML fragment for a definition
180 wxString wxRichTextStyleListBox::CreateHTML(wxRichTextStyleDefinition* def) const
181 {
182 wxString str(wxT("<table><tr>"));
183
184 if (def->GetStyle().GetLeftIndent() > 0)
185 {
186 wxClientDC dc((wxWindow*) this);
187
188 str << wxT("<td width=") << ConvertTenthsMMToPixels(dc, def->GetStyle().GetLeftIndent()) << wxT("></td>");
189 }
190
191 str << wxT("<td nowrap>");
192
193 int size = 5;
194
195 // Standard size is 12, say
196 size += 12 - def->GetStyle().GetFontSize();
197
198 str += wxT("<font");
199
200 str << wxT(" size=") << size;
201
202 if (!def->GetStyle().GetFontFaceName().IsEmpty())
203 str << wxT(" face=\"") << def->GetStyle().GetFontFaceName() << wxT("\"");
204
205 if (def->GetStyle().GetTextColour().Ok())
206 str << wxT(" color=\"#") << ColourToHexString(def->GetStyle().GetTextColour()) << wxT("\"");
207
208 str << wxT(">");
209
210 bool hasBold = false;
211 bool hasItalic = false;
212 bool hasUnderline = false;
213
214 if (def->GetStyle().GetFontWeight() == wxBOLD)
215 hasBold = true;
216 if (def->GetStyle().GetFontStyle() == wxITALIC)
217 hasItalic = true;
218 if (def->GetStyle().GetFontUnderlined())
219 hasUnderline = true;
220
221 if (hasBold)
222 str << wxT("<b>");
223 if (hasItalic)
224 str << wxT("<i>");
225 if (hasUnderline)
226 str << wxT("<u>");
227
228 str += def->GetName();
229
230 if (hasUnderline)
231 str << wxT("</u>");
232 if (hasItalic)
233 str << wxT("</i>");
234 if (hasBold)
235 str << wxT("</b>");
236
237 str << wxT("</font>");
238
239 str += wxT("</td></tr></table>");
240 return str;
241 }
242
243 // Convert units in tends of a millimetre to device units
244 int wxRichTextStyleListBox::ConvertTenthsMMToPixels(wxDC& dc, int units) const
245 {
246 int ppi = dc.GetPPI().x;
247
248 // There are ppi pixels in 254.1 "1/10 mm"
249
250 double pixels = ((double) units * (double)ppi) / 254.1;
251
252 return (int) pixels;
253 }
254
255 /// React to selection
256 void wxRichTextStyleListBox::OnSelect(wxCommandEvent& WXUNUSED(event))
257 {
258 #if 0
259 wxRichTextStyleDefinition* def = GetStyle(event.GetSelection());
260 if (def)
261 {
262 wxMessageBox(def->GetName());
263 }
264 #endif
265 }
266
267 void wxRichTextStyleListBox::OnLeftDown(wxMouseEvent& event)
268 {
269 wxVListBox::OnLeftDown(event);
270
271 int item = HitTest(event.GetPosition());
272
273 if ( item != wxNOT_FOUND )
274 {
275 wxRichTextStyleDefinition* def = GetStyle(item);
276 if (def && GetRichTextCtrl())
277 {
278 wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint());
279
280 // Flags are defined within each definition, so only certain
281 // attributes are applied.
282 wxRichTextAttr attr(def->GetStyle());
283
284 if (m_richTextCtrl->HasSelection())
285 m_richTextCtrl->SetStyle(m_richTextCtrl->GetSelectionRange(), attr);
286 else
287 m_richTextCtrl->SetDefaultStyle(attr);
288
289 m_richTextCtrl->SetFocus();
290 }
291 }
292 }
293
294 #if 0
295 wxColour wxRichTextStyleListBox::GetSelectedTextColour(const wxColour& colFg) const
296 {
297 return *wxBLACK;
298 }
299
300 wxColour wxRichTextStyleListBox::GetSelectedTextBgColour(const wxColour& colBg) const
301 {
302 return *wxWHITE;
303 }
304 #endif
305
306 #endif
307 // wxUSE_HTML
308
309 #endif
310 // wxUSE_RICHTEXT