1 | // Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team |
---|
2 | // |
---|
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this |
---|
4 | // software and associated documentation files (the "Software"), to deal in the Software |
---|
5 | // without restriction, including without limitation the rights to use, copy, modify, merge, |
---|
6 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons |
---|
7 | // to whom the Software is furnished to do so, subject to the following conditions: |
---|
8 | // |
---|
9 | // The above copyright notice and this permission notice shall be included in all copies or |
---|
10 | // substantial portions of the Software. |
---|
11 | // |
---|
12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
---|
13 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
---|
14 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE |
---|
15 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
---|
16 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
---|
17 | // DEALINGS IN THE SOFTWARE. |
---|
18 | |
---|
19 | using System; |
---|
20 | using System.ComponentModel; |
---|
21 | using System.Reflection; |
---|
22 | using System.Text; |
---|
23 | |
---|
24 | namespace ICSharpCode.AvalonEdit |
---|
25 | { |
---|
26 | /// <summary> |
---|
27 | /// A container for the text editor options. |
---|
28 | /// </summary> |
---|
29 | [Serializable] |
---|
30 | public class TextEditorOptions : INotifyPropertyChanged |
---|
31 | { |
---|
32 | #region ctor |
---|
33 | /// <summary> |
---|
34 | /// Initializes an empty instance of TextEditorOptions. |
---|
35 | /// </summary> |
---|
36 | public TextEditorOptions() |
---|
37 | { |
---|
38 | } |
---|
39 | |
---|
40 | /// <summary> |
---|
41 | /// Initializes a new instance of TextEditorOptions by copying all values |
---|
42 | /// from <paramref name="options"/> to the new instance. |
---|
43 | /// </summary> |
---|
44 | public TextEditorOptions(TextEditorOptions options) |
---|
45 | { |
---|
46 | // get all the fields in the class |
---|
47 | FieldInfo[] fields = typeof(TextEditorOptions).GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); |
---|
48 | |
---|
49 | // copy each value over to 'this' |
---|
50 | foreach(FieldInfo fi in fields) { |
---|
51 | if (!fi.IsNotSerialized) |
---|
52 | fi.SetValue(this, fi.GetValue(options)); |
---|
53 | } |
---|
54 | } |
---|
55 | #endregion |
---|
56 | |
---|
57 | #region PropertyChanged handling |
---|
58 | /// <inheritdoc/> |
---|
59 | [field: NonSerialized] |
---|
60 | public event PropertyChangedEventHandler PropertyChanged; |
---|
61 | |
---|
62 | /// <summary> |
---|
63 | /// Raises the PropertyChanged event. |
---|
64 | /// </summary> |
---|
65 | /// <param name="propertyName">The name of the changed property.</param> |
---|
66 | protected void OnPropertyChanged(string propertyName) |
---|
67 | { |
---|
68 | OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); |
---|
69 | } |
---|
70 | |
---|
71 | /// <summary> |
---|
72 | /// Raises the PropertyChanged event. |
---|
73 | /// </summary> |
---|
74 | protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) |
---|
75 | { |
---|
76 | if (PropertyChanged != null) { |
---|
77 | PropertyChanged(this, e); |
---|
78 | } |
---|
79 | } |
---|
80 | #endregion |
---|
81 | |
---|
82 | #region ShowSpaces / ShowTabs / ShowEndOfLine / ShowBoxForControlCharacters |
---|
83 | bool showSpaces; |
---|
84 | |
---|
85 | /// <summary> |
---|
86 | /// Gets/Sets whether to show · for spaces. |
---|
87 | /// </summary> |
---|
88 | /// <remarks>The default value is <c>false</c>.</remarks> |
---|
89 | [DefaultValue(false)] |
---|
90 | public virtual bool ShowSpaces { |
---|
91 | get { return showSpaces; } |
---|
92 | set { |
---|
93 | if (showSpaces != value) { |
---|
94 | showSpaces = value; |
---|
95 | OnPropertyChanged("ShowSpaces"); |
---|
96 | } |
---|
97 | } |
---|
98 | } |
---|
99 | |
---|
100 | bool showTabs; |
---|
101 | |
---|
102 | /// <summary> |
---|
103 | /// Gets/Sets whether to show » for tabs. |
---|
104 | /// </summary> |
---|
105 | /// <remarks>The default value is <c>false</c>.</remarks> |
---|
106 | [DefaultValue(false)] |
---|
107 | public virtual bool ShowTabs { |
---|
108 | get { return showTabs; } |
---|
109 | set { |
---|
110 | if (showTabs != value) { |
---|
111 | showTabs = value; |
---|
112 | OnPropertyChanged("ShowTabs"); |
---|
113 | } |
---|
114 | } |
---|
115 | } |
---|
116 | |
---|
117 | bool showEndOfLine; |
---|
118 | |
---|
119 | /// <summary> |
---|
120 | /// Gets/Sets whether to show ¶ at the end of lines. |
---|
121 | /// </summary> |
---|
122 | /// <remarks>The default value is <c>false</c>.</remarks> |
---|
123 | [DefaultValue(false)] |
---|
124 | public virtual bool ShowEndOfLine { |
---|
125 | get { return showEndOfLine; } |
---|
126 | set { |
---|
127 | if (showEndOfLine != value) { |
---|
128 | showEndOfLine = value; |
---|
129 | OnPropertyChanged("ShowEndOfLine"); |
---|
130 | } |
---|
131 | } |
---|
132 | } |
---|
133 | |
---|
134 | bool showBoxForControlCharacters = true; |
---|
135 | |
---|
136 | /// <summary> |
---|
137 | /// Gets/Sets whether to show a box with the hex code for control characters. |
---|
138 | /// </summary> |
---|
139 | /// <remarks>The default value is <c>true</c>.</remarks> |
---|
140 | [DefaultValue(true)] |
---|
141 | public virtual bool ShowBoxForControlCharacters { |
---|
142 | get { return showBoxForControlCharacters; } |
---|
143 | set { |
---|
144 | if (showBoxForControlCharacters != value) { |
---|
145 | showBoxForControlCharacters = value; |
---|
146 | OnPropertyChanged("ShowBoxForControlCharacters"); |
---|
147 | } |
---|
148 | } |
---|
149 | } |
---|
150 | #endregion |
---|
151 | |
---|
152 | #region EnableHyperlinks |
---|
153 | bool enableHyperlinks = true; |
---|
154 | |
---|
155 | /// <summary> |
---|
156 | /// Gets/Sets whether to enable clickable hyperlinks in the editor. |
---|
157 | /// </summary> |
---|
158 | /// <remarks>The default value is <c>true</c>.</remarks> |
---|
159 | [DefaultValue(true)] |
---|
160 | public virtual bool EnableHyperlinks { |
---|
161 | get { return enableHyperlinks; } |
---|
162 | set { |
---|
163 | if (enableHyperlinks != value) { |
---|
164 | enableHyperlinks = value; |
---|
165 | OnPropertyChanged("EnableHyperlinks"); |
---|
166 | } |
---|
167 | } |
---|
168 | } |
---|
169 | |
---|
170 | bool enableEmailHyperlinks = true; |
---|
171 | |
---|
172 | /// <summary> |
---|
173 | /// Gets/Sets whether to enable clickable hyperlinks for e-mail addresses in the editor. |
---|
174 | /// </summary> |
---|
175 | /// <remarks>The default value is <c>true</c>.</remarks> |
---|
176 | [DefaultValue(true)] |
---|
177 | public virtual bool EnableEmailHyperlinks { |
---|
178 | get { return enableEmailHyperlinks; } |
---|
179 | set { |
---|
180 | if (enableEmailHyperlinks != value) { |
---|
181 | enableEmailHyperlinks = value; |
---|
182 | OnPropertyChanged("EnableEMailHyperlinks"); |
---|
183 | } |
---|
184 | } |
---|
185 | } |
---|
186 | |
---|
187 | bool requireControlModifierForHyperlinkClick = true; |
---|
188 | |
---|
189 | /// <summary> |
---|
190 | /// Gets/Sets whether the user needs to press Control to click hyperlinks. |
---|
191 | /// The default value is true. |
---|
192 | /// </summary> |
---|
193 | /// <remarks>The default value is <c>true</c>.</remarks> |
---|
194 | [DefaultValue(true)] |
---|
195 | public virtual bool RequireControlModifierForHyperlinkClick { |
---|
196 | get { return requireControlModifierForHyperlinkClick; } |
---|
197 | set { |
---|
198 | if (requireControlModifierForHyperlinkClick != value) { |
---|
199 | requireControlModifierForHyperlinkClick = value; |
---|
200 | OnPropertyChanged("RequireControlModifierForHyperlinkClick"); |
---|
201 | } |
---|
202 | } |
---|
203 | } |
---|
204 | #endregion |
---|
205 | |
---|
206 | #region TabSize / IndentationSize / ConvertTabsToSpaces / GetIndentationString |
---|
207 | // I'm using '_' prefixes for the fields here to avoid confusion with the local variables |
---|
208 | // in the methods below. |
---|
209 | // The fields should be accessed only by their property - the fields might not be used |
---|
210 | // if someone overrides the property. |
---|
211 | |
---|
212 | int indentationSize = 4; |
---|
213 | |
---|
214 | /// <summary> |
---|
215 | /// Gets/Sets the width of one indentation unit. |
---|
216 | /// </summary> |
---|
217 | /// <remarks>The default value is 4.</remarks> |
---|
218 | [DefaultValue(4)] |
---|
219 | public virtual int IndentationSize { |
---|
220 | get { return indentationSize; } |
---|
221 | set { |
---|
222 | if (value < 1) |
---|
223 | throw new ArgumentOutOfRangeException("value", value, "value must be positive"); |
---|
224 | // sanity check; a too large value might cause WPF to crash internally much later |
---|
225 | // (it only crashed in the hundred thousands for me; but might crash earlier with larger fonts) |
---|
226 | if (value > 1000) |
---|
227 | throw new ArgumentOutOfRangeException("value", value, "indentation size is too large"); |
---|
228 | if (indentationSize != value) { |
---|
229 | indentationSize = value; |
---|
230 | OnPropertyChanged("IndentationSize"); |
---|
231 | OnPropertyChanged("IndentationString"); |
---|
232 | } |
---|
233 | } |
---|
234 | } |
---|
235 | |
---|
236 | bool convertTabsToSpaces; |
---|
237 | |
---|
238 | /// <summary> |
---|
239 | /// Gets/Sets whether to use spaces for indentation instead of tabs. |
---|
240 | /// </summary> |
---|
241 | /// <remarks>The default value is <c>false</c>.</remarks> |
---|
242 | [DefaultValue(false)] |
---|
243 | public virtual bool ConvertTabsToSpaces { |
---|
244 | get { return convertTabsToSpaces; } |
---|
245 | set { |
---|
246 | if (convertTabsToSpaces != value) { |
---|
247 | convertTabsToSpaces = value; |
---|
248 | OnPropertyChanged("ConvertTabsToSpaces"); |
---|
249 | OnPropertyChanged("IndentationString"); |
---|
250 | } |
---|
251 | } |
---|
252 | } |
---|
253 | |
---|
254 | /// <summary> |
---|
255 | /// Gets the text used for indentation. |
---|
256 | /// </summary> |
---|
257 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods")] |
---|
258 | [Browsable(false)] |
---|
259 | public string IndentationString { |
---|
260 | get { return GetIndentationString(1); } |
---|
261 | } |
---|
262 | |
---|
263 | /// <summary> |
---|
264 | /// Gets text required to indent from the specified <paramref name="column"/> to the next indentation level. |
---|
265 | /// </summary> |
---|
266 | public virtual string GetIndentationString(int column) |
---|
267 | { |
---|
268 | if (column < 1) |
---|
269 | throw new ArgumentOutOfRangeException("column", column, "Value must be at least 1."); |
---|
270 | int indentationSize = this.IndentationSize; |
---|
271 | if (ConvertTabsToSpaces) { |
---|
272 | return new string(' ', indentationSize - ((column - 1) % indentationSize)); |
---|
273 | } else { |
---|
274 | return "\t"; |
---|
275 | } |
---|
276 | } |
---|
277 | #endregion |
---|
278 | |
---|
279 | bool cutCopyWholeLine = true; |
---|
280 | |
---|
281 | /// <summary> |
---|
282 | /// Gets/Sets whether copying without a selection copies the whole current line. |
---|
283 | /// </summary> |
---|
284 | [DefaultValue(true)] |
---|
285 | public virtual bool CutCopyWholeLine { |
---|
286 | get { return cutCopyWholeLine; } |
---|
287 | set { |
---|
288 | if (cutCopyWholeLine != value) { |
---|
289 | cutCopyWholeLine = value; |
---|
290 | OnPropertyChanged("CutCopyWholeLine"); |
---|
291 | } |
---|
292 | } |
---|
293 | } |
---|
294 | |
---|
295 | bool allowScrollBelowDocument; |
---|
296 | |
---|
297 | /// <summary> |
---|
298 | /// Gets/Sets whether the user can scroll below the bottom of the document. |
---|
299 | /// The default value is false; but it a good idea to set this property to true when using folding. |
---|
300 | /// </summary> |
---|
301 | [DefaultValue(false)] |
---|
302 | public virtual bool AllowScrollBelowDocument { |
---|
303 | get { return allowScrollBelowDocument; } |
---|
304 | set { |
---|
305 | if (allowScrollBelowDocument != value) { |
---|
306 | allowScrollBelowDocument = value; |
---|
307 | OnPropertyChanged("AllowScrollBelowDocument"); |
---|
308 | } |
---|
309 | } |
---|
310 | } |
---|
311 | |
---|
312 | double wordWrapIndentation = 0; |
---|
313 | |
---|
314 | /// <summary> |
---|
315 | /// Gets/Sets the indentation used for all lines except the first when word-wrapping. |
---|
316 | /// The default value is 0. |
---|
317 | /// </summary> |
---|
318 | [DefaultValue(0.0)] |
---|
319 | public virtual double WordWrapIndentation { |
---|
320 | get { return wordWrapIndentation; } |
---|
321 | set { |
---|
322 | if (double.IsNaN(value) || double.IsInfinity(value)) |
---|
323 | throw new ArgumentOutOfRangeException("value", value, "value must not be NaN/infinity"); |
---|
324 | if (value != wordWrapIndentation) { |
---|
325 | wordWrapIndentation = value; |
---|
326 | OnPropertyChanged("WordWrapIndentation"); |
---|
327 | } |
---|
328 | } |
---|
329 | } |
---|
330 | |
---|
331 | bool inheritWordWrapIndentation = true; |
---|
332 | |
---|
333 | /// <summary> |
---|
334 | /// Gets/Sets whether the indentation is inherited from the first line when word-wrapping. |
---|
335 | /// The default value is true. |
---|
336 | /// </summary> |
---|
337 | /// <remarks>When combined with <see cref="WordWrapIndentation"/>, the inherited indentation is added to the word wrap indentation.</remarks> |
---|
338 | [DefaultValue(true)] |
---|
339 | public virtual bool InheritWordWrapIndentation { |
---|
340 | get { return inheritWordWrapIndentation; } |
---|
341 | set { |
---|
342 | if (value != inheritWordWrapIndentation) { |
---|
343 | inheritWordWrapIndentation = value; |
---|
344 | OnPropertyChanged("InheritWordWrapIndentation"); |
---|
345 | } |
---|
346 | } |
---|
347 | } |
---|
348 | |
---|
349 | bool enableRectangularSelection = true; |
---|
350 | |
---|
351 | /// <summary> |
---|
352 | /// Enables rectangular selection (press ALT and select a rectangle) |
---|
353 | /// </summary> |
---|
354 | [DefaultValue(true)] |
---|
355 | public bool EnableRectangularSelection { |
---|
356 | get { return enableRectangularSelection; } |
---|
357 | set { |
---|
358 | if (enableRectangularSelection != value) { |
---|
359 | enableRectangularSelection = value; |
---|
360 | OnPropertyChanged("EnableRectangularSelection"); |
---|
361 | } |
---|
362 | } |
---|
363 | } |
---|
364 | |
---|
365 | bool enableTextDragDrop = true; |
---|
366 | |
---|
367 | /// <summary> |
---|
368 | /// Enable dragging text within the text area. |
---|
369 | /// </summary> |
---|
370 | [DefaultValue(true)] |
---|
371 | public bool EnableTextDragDrop { |
---|
372 | get { return enableTextDragDrop; } |
---|
373 | set { |
---|
374 | if (enableTextDragDrop != value) { |
---|
375 | enableTextDragDrop = value; |
---|
376 | OnPropertyChanged("EnableTextDragDrop"); |
---|
377 | } |
---|
378 | } |
---|
379 | } |
---|
380 | |
---|
381 | bool enableVirtualSpace; |
---|
382 | |
---|
383 | /// <summary> |
---|
384 | /// Gets/Sets whether the user can set the caret behind the line ending |
---|
385 | /// (into "virtual space"). |
---|
386 | /// Note that virtual space is always used (independent from this setting) |
---|
387 | /// when doing rectangle selections. |
---|
388 | /// </summary> |
---|
389 | [DefaultValue(false)] |
---|
390 | public virtual bool EnableVirtualSpace { |
---|
391 | get { return enableVirtualSpace; } |
---|
392 | set { |
---|
393 | if (enableVirtualSpace != value) { |
---|
394 | enableVirtualSpace = value; |
---|
395 | OnPropertyChanged("EnableVirtualSpace"); |
---|
396 | } |
---|
397 | } |
---|
398 | } |
---|
399 | |
---|
400 | bool enableImeSupport = true; |
---|
401 | |
---|
402 | /// <summary> |
---|
403 | /// Gets/Sets whether the support for Input Method Editors (IME) |
---|
404 | /// for non-alphanumeric scripts (Chinese, Japanese, Korean, ...) is enabled. |
---|
405 | /// </summary> |
---|
406 | [DefaultValue(true)] |
---|
407 | public virtual bool EnableImeSupport { |
---|
408 | get { return enableImeSupport; } |
---|
409 | set { |
---|
410 | if (enableImeSupport != value) { |
---|
411 | enableImeSupport = value; |
---|
412 | OnPropertyChanged("EnableImeSupport"); |
---|
413 | } |
---|
414 | } |
---|
415 | } |
---|
416 | |
---|
417 | bool showColumnRuler = false; |
---|
418 | |
---|
419 | /// <summary> |
---|
420 | /// Gets/Sets whether the column ruler should be shown. |
---|
421 | /// </summary> |
---|
422 | [DefaultValue(false)] |
---|
423 | public virtual bool ShowColumnRuler { |
---|
424 | get { return showColumnRuler; } |
---|
425 | set { |
---|
426 | if (showColumnRuler != value) { |
---|
427 | showColumnRuler = value; |
---|
428 | OnPropertyChanged("ShowColumnRuler"); |
---|
429 | } |
---|
430 | } |
---|
431 | } |
---|
432 | |
---|
433 | int columnRulerPosition = 80; |
---|
434 | |
---|
435 | /// <summary> |
---|
436 | /// Gets/Sets where the column ruler should be shown. |
---|
437 | /// </summary> |
---|
438 | [DefaultValue(80)] |
---|
439 | public virtual int ColumnRulerPosition { |
---|
440 | get { return columnRulerPosition; } |
---|
441 | set { |
---|
442 | if (columnRulerPosition != value) { |
---|
443 | columnRulerPosition = value; |
---|
444 | OnPropertyChanged("ColumnRulerPosition"); |
---|
445 | } |
---|
446 | } |
---|
447 | } |
---|
448 | |
---|
449 | bool highlightCurrentLine = false; |
---|
450 | |
---|
451 | /// <summary> |
---|
452 | /// Gets/Sets if current line should be shown. |
---|
453 | /// </summary> |
---|
454 | [DefaultValue(false)] |
---|
455 | public virtual bool HighlightCurrentLine { |
---|
456 | get { return highlightCurrentLine; } |
---|
457 | set { |
---|
458 | if (highlightCurrentLine != value) { |
---|
459 | highlightCurrentLine = value; |
---|
460 | OnPropertyChanged("HighlightCurrentLine"); |
---|
461 | } |
---|
462 | } |
---|
463 | } |
---|
464 | |
---|
465 | bool hideCursorWhileTyping = true; |
---|
466 | |
---|
467 | /// <summary> |
---|
468 | /// Gets/Sets if mouse cursor should be hidden while user is typing. |
---|
469 | /// </summary> |
---|
470 | [DefaultValue(true)] |
---|
471 | public bool HideCursorWhileTyping { |
---|
472 | get { return hideCursorWhileTyping; } |
---|
473 | set { |
---|
474 | if (hideCursorWhileTyping != value) { |
---|
475 | hideCursorWhileTyping = value; |
---|
476 | OnPropertyChanged("HideCursorWhileTyping"); |
---|
477 | } |
---|
478 | } |
---|
479 | } |
---|
480 | |
---|
481 | bool allowToggleOverstrikeMode = false; |
---|
482 | |
---|
483 | /// <summary> |
---|
484 | /// Gets/Sets if the user is allowed to enable/disable overstrike mode. |
---|
485 | /// </summary> |
---|
486 | [DefaultValue(false)] |
---|
487 | public bool AllowToggleOverstrikeMode { |
---|
488 | get { return allowToggleOverstrikeMode; } |
---|
489 | set { |
---|
490 | if (allowToggleOverstrikeMode != value) { |
---|
491 | allowToggleOverstrikeMode = value; |
---|
492 | OnPropertyChanged("AllowToggleOverstrikeMode"); |
---|
493 | } |
---|
494 | } |
---|
495 | } |
---|
496 | } |
---|
497 | } |
---|