Skip to content
This repository was archived by the owner on Oct 16, 2020. It is now read-only.

Commit dd292ff

Browse files
committed
Fix #506: Tabs/spaces not shown in text editor for C# files
1 parent e302927 commit dd292ff

1 file changed

Lines changed: 79 additions & 159 deletions

File tree

src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs

Lines changed: 79 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
using System.Collections.Generic;
2121

2222
using System.ComponentModel;
23+
using System.Reflection;
2324
using System.Threading;
2425
using ICSharpCode.AvalonEdit;
2526
using ICSharpCode.AvalonEdit.Highlighting;
@@ -83,9 +84,9 @@ public void Attach(ITextEditor editor)
8384
// Create instance of options adapter and register it as service
8485
var formattingPolicy = CSharpFormattingPolicies.Instance.GetProjectOptions(
8586
SD.ProjectService.FindProjectContainingFile(editor.FileName));
86-
options = new CodeEditorFormattingOptionsAdapter(editor.Options, formattingPolicy.OptionsContainer);
8787
var textEditor = editor.GetService<TextEditor>();
8888
if (textEditor != null) {
89+
options = new CodeEditorFormattingOptionsAdapter(textEditor.Options, editor.Options, formattingPolicy.OptionsContainer);
8990
var textViewServices = textEditor.TextArea.TextView.Services;
9091

9192
// Unregister any previous ITextEditorOptions instance from editor, if existing, register our impl.
@@ -94,7 +95,7 @@ public void Attach(ITextEditor editor)
9495

9596
// Set TextEditor's options to same object
9697
originalEditorOptions = textEditor.Options;
97-
textEditor.Options = options;
98+
textEditor.Options = options.TextEditorOptions;
9899
}
99100
}
100101

@@ -110,7 +111,7 @@ public void Detach()
110111
textView.Services.RemoveService(typeof(ITextEditorOptions));
111112

112113
// Reset TextEditor options, too?
113-
if ((textEditor.Options != null) && (textEditor.Options == options))
114+
if ((textEditor.Options != null) && (textEditor.Options == options.TextEditorOptions))
114115
textEditor.Options = originalEditorOptions;
115116
}
116117

@@ -128,225 +129,144 @@ public void Detach()
128129
}
129130
}
130131

131-
class CodeEditorFormattingOptionsAdapter : TextEditorOptions, ITextEditorOptions, ICodeEditorOptions
132+
class CodeEditorFormattingOptionsAdapter : ITextEditorOptions, INotifyPropertyChanged
132133
{
133134
CSharpFormattingOptionsContainer container;
134-
readonly ITextEditorOptions globalOptions;
135-
readonly ICodeEditorOptions globalCodeEditorOptions;
135+
readonly TextEditorOptions avalonEditOptions;
136+
readonly TextEditorOptions originalAvalonEditOptions;
137+
readonly ITextEditorOptions originalSDOptions;
136138

137-
public CodeEditorFormattingOptionsAdapter(ITextEditorOptions globalOptions, CSharpFormattingOptionsContainer container)
139+
public CodeEditorFormattingOptionsAdapter(TextEditorOptions originalAvalonEditOptions, ITextEditorOptions originalSDOptions, CSharpFormattingOptionsContainer container)
138140
{
139-
if (globalOptions == null)
140-
throw new ArgumentNullException("globalOptions");
141+
if (originalAvalonEditOptions == null)
142+
throw new ArgumentNullException("originalAvalonEditOptions");
143+
if (originalSDOptions == null)
144+
throw new ArgumentNullException("originalSDOptions");
141145
if (container == null)
142146
throw new ArgumentNullException("container");
143147

144-
this.globalOptions = globalOptions;
145-
this.globalCodeEditorOptions = globalOptions as ICodeEditorOptions;
148+
this.originalAvalonEditOptions = originalAvalonEditOptions;
149+
this.avalonEditOptions = new TextEditorOptions(originalAvalonEditOptions);
150+
this.originalSDOptions = originalSDOptions;
146151
this.container = container;
147152

153+
// Update overridden options once
154+
UpdateOverriddenProperties();
155+
148156
CSharpFormattingPolicies.Instance.FormattingPolicyUpdated += OnFormattingPolicyUpdated;
149-
globalOptions.PropertyChanged += OnGlobalOptionsPropertyChanged;
157+
this.originalAvalonEditOptions.PropertyChanged += OnOrigAvalonOptionsPropertyChanged;
158+
this.originalSDOptions.PropertyChanged += OnSDOptionsPropertyChanged;
150159
}
151160

152161
void OnFormattingPolicyUpdated(object sender, CSharpBinding.FormattingStrategy.CSharpFormattingPolicyUpdateEventArgs e)
153162
{
163+
// Update editor options from changed policy
164+
UpdateOverriddenProperties();
165+
154166
OnPropertyChanged("IndentationSize");
167+
OnPropertyChanged("IndentationString");
155168
OnPropertyChanged("ConvertTabsToSpaces");
156169
}
157-
158-
void OnGlobalOptionsPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
170+
171+
void UpdateOverriddenProperties()
159172
{
160-
OnPropertyChanged(e.PropertyName);
173+
avalonEditOptions.IndentationSize = container.GetEffectiveIndentationSize() ?? originalSDOptions.IndentationSize;
174+
avalonEditOptions.ConvertTabsToSpaces = container.GetEffectiveConvertTabsToSpaces() ?? originalSDOptions.ConvertTabsToSpaces;
161175
}
162-
163-
#region ITextEditorOptions implementation
164176

165-
public override int IndentationSize {
166-
get {
167-
return container.GetEffectiveIndentationSize() ?? globalOptions.IndentationSize;
177+
void OnOrigAvalonOptionsPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
178+
{
179+
if ((e.PropertyName != "IndentationSize") && (e.PropertyName != "IndentationString") && (e.PropertyName != "ConvertTabsToSpaces")) {
180+
// Update values in our own TextEditorOptions instance
181+
PropertyInfo propertyInfo = typeof(TextEditorOptions).GetProperty(e.PropertyName);
182+
if (propertyInfo != null) {
183+
propertyInfo.SetValue(avalonEditOptions, propertyInfo.GetValue(originalAvalonEditOptions));
184+
}
185+
} else {
186+
UpdateOverriddenProperties();
168187
}
188+
OnPropertyChanged(e.PropertyName);
169189
}
170190

171-
public override bool ConvertTabsToSpaces {
172-
get {
173-
return container.GetEffectiveConvertTabsToSpaces() ?? globalOptions.ConvertTabsToSpaces;
174-
}
191+
void OnSDOptionsPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
192+
{
193+
OnPropertyChanged(e.PropertyName);
175194
}
176-
177-
public bool AutoInsertBlockEnd {
178-
get {
179-
return globalOptions.AutoInsertBlockEnd;
195+
196+
public event PropertyChangedEventHandler PropertyChanged;
197+
198+
void OnPropertyChanged(string propertyName)
199+
{
200+
if (PropertyChanged != null) {
201+
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
180202
}
181203
}
182-
183-
public int VerticalRulerColumn {
204+
205+
public TextEditorOptions TextEditorOptions
206+
{
184207
get {
185-
return globalOptions.VerticalRulerColumn;
208+
return avalonEditOptions;
186209
}
187210
}
188211

189-
public bool UnderlineErrors {
212+
#region Overridden properties
213+
214+
public int IndentationSize {
190215
get {
191-
return globalOptions.UnderlineErrors;
216+
// Get value from own TextEditorOptions instance
217+
return avalonEditOptions.IndentationSize;
192218
}
193219
}
194220

195-
public string FontFamily {
221+
public string IndentationString {
196222
get {
197-
return globalOptions.FontFamily;
223+
// Get value from own TextEditorOptions instance
224+
return avalonEditOptions.IndentationString;
198225
}
199226
}
200227

201-
public double FontSize {
228+
public bool ConvertTabsToSpaces {
202229
get {
203-
return globalOptions.FontSize;
230+
// Get value from own TextEditorOptions instance
231+
return avalonEditOptions.ConvertTabsToSpaces;
204232
}
205233
}
206-
234+
207235
#endregion
236+
237+
#region Rest of ITextEditorOptions implementation
208238

209-
public override bool AllowScrollBelowDocument {
210-
get {
211-
return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.AllowScrollBelowDocument : default(bool);
212-
}
213-
set {
214-
if (globalCodeEditorOptions != null) {
215-
globalCodeEditorOptions.AllowScrollBelowDocument = value;
216-
}
217-
}
218-
}
219-
220-
public bool ShowLineNumbers {
221-
get {
222-
return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.ShowLineNumbers : default(bool);
223-
}
224-
set {
225-
if (globalCodeEditorOptions != null) {
226-
globalCodeEditorOptions.ShowLineNumbers = value;
227-
}
228-
}
229-
}
230-
231-
public bool EnableChangeMarkerMargin {
232-
get {
233-
return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.EnableChangeMarkerMargin : default(bool);
234-
}
235-
set {
236-
if (globalCodeEditorOptions != null) {
237-
globalCodeEditorOptions.EnableChangeMarkerMargin = value;
238-
}
239-
}
240-
}
241-
242-
public bool WordWrap {
243-
get {
244-
return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.WordWrap : default(bool);
245-
}
246-
set {
247-
if (globalCodeEditorOptions != null) {
248-
globalCodeEditorOptions.WordWrap = value;
249-
}
250-
}
251-
}
252-
253-
public bool CtrlClickGoToDefinition {
254-
get {
255-
return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.CtrlClickGoToDefinition : default(bool);
256-
}
257-
set {
258-
if (globalCodeEditorOptions != null) {
259-
globalCodeEditorOptions.CtrlClickGoToDefinition = value;
260-
}
261-
}
262-
}
263-
264-
public bool MouseWheelZoom {
265-
get {
266-
return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.MouseWheelZoom : default(bool);
267-
}
268-
set {
269-
if (globalCodeEditorOptions != null) {
270-
globalCodeEditorOptions.MouseWheelZoom = value;
271-
}
272-
}
273-
}
274-
275-
public bool HighlightBrackets {
239+
public bool AutoInsertBlockEnd {
276240
get {
277-
return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.HighlightBrackets : default(bool);
278-
}
279-
set {
280-
if (globalCodeEditorOptions != null) {
281-
globalCodeEditorOptions.HighlightBrackets = value;
282-
}
241+
return originalSDOptions.AutoInsertBlockEnd;
283242
}
284243
}
285244

286-
public bool HighlightSymbol {
245+
public int VerticalRulerColumn {
287246
get {
288-
return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.HighlightSymbol : default(bool);
289-
}
290-
set {
291-
if (globalCodeEditorOptions != null) {
292-
globalCodeEditorOptions.HighlightSymbol = value;
293-
}
247+
return originalSDOptions.VerticalRulerColumn;
294248
}
295249
}
296250

297-
public bool EnableAnimations {
251+
public bool UnderlineErrors {
298252
get {
299-
return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.EnableAnimations : default(bool);
300-
}
301-
set {
302-
if (globalCodeEditorOptions != null) {
303-
globalCodeEditorOptions.EnableAnimations = value;
304-
}
253+
return originalSDOptions.UnderlineErrors;
305254
}
306255
}
307256

308-
public bool UseSmartIndentation {
257+
public string FontFamily {
309258
get {
310-
return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.UseSmartIndentation : default(bool);
311-
}
312-
set {
313-
if (globalCodeEditorOptions != null) {
314-
globalCodeEditorOptions.UseSmartIndentation = value;
315-
}
259+
return originalSDOptions.FontFamily;
316260
}
317261
}
318262

319-
public bool EnableFolding {
263+
public double FontSize {
320264
get {
321-
return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.EnableFolding : default(bool);
322-
}
323-
set {
324-
if (globalCodeEditorOptions != null) {
325-
globalCodeEditorOptions.EnableFolding = value;
326-
}
265+
return originalSDOptions.FontSize;
327266
}
328267
}
329268

330-
public bool EnableQuickClassBrowser {
331-
get {
332-
return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.EnableQuickClassBrowser : default(bool);
333-
}
334-
set {
335-
if (globalCodeEditorOptions != null) {
336-
globalCodeEditorOptions.EnableQuickClassBrowser = value;
337-
}
338-
}
339-
}
269+
#endregion
340270

341-
public bool ShowHiddenDefinitions {
342-
get {
343-
return (globalCodeEditorOptions != null) ? globalCodeEditorOptions.ShowHiddenDefinitions : default(bool);
344-
}
345-
set {
346-
if (globalCodeEditorOptions != null) {
347-
globalCodeEditorOptions.ShowHiddenDefinitions = value;
348-
}
349-
}
350-
}
351271
}
352272
}

0 commit comments

Comments
 (0)