1919using System ;
2020using System . Collections . Generic ;
2121
22+ using System . ComponentModel ;
2223using System . Threading ;
24+ using ICSharpCode . AvalonEdit ;
2325using ICSharpCode . AvalonEdit . Highlighting ;
2426using ICSharpCode . NRefactory ;
2527using ICSharpCode . NRefactory . TypeSystem ;
@@ -62,6 +64,8 @@ public class CSharpTextEditorExtension : ITextEditorExtension
6264 IList < IContextActionProvider > contextActionProviders ;
6365 CodeManipulation codeManipulation ;
6466 CaretReferenceHighlightRenderer renderer ;
67+ CodeEditorFormattingOptionsAdapter options ;
68+ TextEditorOptions originalEditorOptions ;
6569
6670 public void Attach ( ITextEditor editor )
6771 {
@@ -70,14 +74,46 @@ public void Attach(ITextEditor editor)
7074 codeManipulation = new CodeManipulation ( editor ) ;
7175 renderer = new CaretReferenceHighlightRenderer ( editor ) ;
7276
77+ // Patch editor options (indentation) to project-specific settings
7378 if ( ! editor . ContextActionProviders . IsReadOnly ) {
7479 contextActionProviders = AddInTree . BuildItems < IContextActionProvider > ( "/SharpDevelop/ViewContent/TextEditor/C#/ContextActions" , null ) ;
7580 editor . ContextActionProviders . AddRange ( contextActionProviders ) ;
7681 }
82+
83+ // Create instance of options adapter and register it as service
84+ var formattingPolicy = CSharpFormattingPolicies . Instance . GetProjectOptions (
85+ SD . ProjectService . FindProjectContainingFile ( editor . FileName ) ) ;
86+ options = new CodeEditorFormattingOptionsAdapter ( editor . Options , formattingPolicy . OptionsContainer ) ;
87+ var textEditor = editor . GetService < TextEditor > ( ) ;
88+ if ( textEditor != null ) {
89+ var textViewServices = textEditor . TextArea . TextView . Services ;
90+
91+ // Unregister any previous ITextEditorOptions instance from editor, if existing, register our impl.
92+ textViewServices . RemoveService ( typeof ( ITextEditorOptions ) ) ;
93+ textViewServices . AddService ( typeof ( ITextEditorOptions ) , options ) ;
94+
95+ // Set TextEditor's options to same object
96+ originalEditorOptions = textEditor . Options ;
97+ textEditor . Options = options ;
98+ }
7799 }
78100
79101 public void Detach ( )
80102 {
103+ var textEditor = editor . GetService < TextEditor > ( ) ;
104+ if ( textEditor != null ) {
105+ var textView = textEditor . TextArea . TextView ;
106+
107+ // Unregister our ITextEditorOptions instance from editor
108+ var optionsService = textView . GetService < ITextEditorOptions > ( ) ;
109+ if ( ( optionsService != null ) && ( optionsService == options ) )
110+ textView . Services . RemoveService ( typeof ( ITextEditorOptions ) ) ;
111+
112+ // Reset TextEditor options, too?
113+ if ( ( textEditor . Options != null ) && ( textEditor . Options == options ) )
114+ textEditor . Options = originalEditorOptions ;
115+ }
116+
81117 codeManipulation . Dispose ( ) ;
82118 if ( inspectionManager != null ) {
83119 inspectionManager . Dispose ( ) ;
@@ -87,7 +123,230 @@ public void Detach()
87123 editor . ContextActionProviders . RemoveAll ( contextActionProviders . Contains ) ;
88124 }
89125 renderer . Dispose ( ) ;
126+ options = null ;
90127 this . editor = null ;
91128 }
92129 }
130+
131+ class CodeEditorFormattingOptionsAdapter : TextEditorOptions , ITextEditorOptions , ICodeEditorOptions
132+ {
133+ CSharpFormattingOptionsContainer container ;
134+ readonly ITextEditorOptions globalOptions ;
135+ readonly ICodeEditorOptions globalCodeEditorOptions ;
136+
137+ public CodeEditorFormattingOptionsAdapter ( ITextEditorOptions globalOptions , CSharpFormattingOptionsContainer container )
138+ {
139+ if ( globalOptions == null )
140+ throw new ArgumentNullException ( "globalOptions" ) ;
141+ if ( container == null )
142+ throw new ArgumentNullException ( "container" ) ;
143+
144+ this . globalOptions = globalOptions ;
145+ this . globalCodeEditorOptions = globalOptions as ICodeEditorOptions ;
146+ this . container = container ;
147+
148+ CSharpFormattingPolicies . Instance . FormattingPolicyUpdated += OnFormattingPolicyUpdated ;
149+ globalOptions . PropertyChanged += OnGlobalOptionsPropertyChanged ;
150+ }
151+
152+ void OnFormattingPolicyUpdated ( object sender , CSharpBinding . FormattingStrategy . CSharpFormattingPolicyUpdateEventArgs e )
153+ {
154+ OnPropertyChanged ( "IndentationSize" ) ;
155+ OnPropertyChanged ( "ConvertTabsToSpaces" ) ;
156+ }
157+
158+ void OnGlobalOptionsPropertyChanged ( object sender , System . ComponentModel . PropertyChangedEventArgs e )
159+ {
160+ OnPropertyChanged ( e . PropertyName ) ;
161+ }
162+
163+ #region ITextEditorOptions implementation
164+
165+ public override int IndentationSize {
166+ get {
167+ return container . GetEffectiveIndentationSize ( ) ?? globalOptions . IndentationSize ;
168+ }
169+ }
170+
171+ public override bool ConvertTabsToSpaces {
172+ get {
173+ return container . GetEffectiveConvertTabsToSpaces ( ) ?? globalOptions . ConvertTabsToSpaces ;
174+ }
175+ }
176+
177+ public bool AutoInsertBlockEnd {
178+ get {
179+ return globalOptions . AutoInsertBlockEnd ;
180+ }
181+ }
182+
183+ public int VerticalRulerColumn {
184+ get {
185+ return globalOptions . VerticalRulerColumn ;
186+ }
187+ }
188+
189+ public bool UnderlineErrors {
190+ get {
191+ return globalOptions . UnderlineErrors ;
192+ }
193+ }
194+
195+ public string FontFamily {
196+ get {
197+ return globalOptions . FontFamily ;
198+ }
199+ }
200+
201+ public double FontSize {
202+ get {
203+ return globalOptions . FontSize ;
204+ }
205+ }
206+
207+ #endregion
208+
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 {
276+ get {
277+ return ( globalCodeEditorOptions != null ) ? globalCodeEditorOptions . HighlightBrackets : default ( bool ) ;
278+ }
279+ set {
280+ if ( globalCodeEditorOptions != null ) {
281+ globalCodeEditorOptions . HighlightBrackets = value ;
282+ }
283+ }
284+ }
285+
286+ public bool HighlightSymbol {
287+ get {
288+ return ( globalCodeEditorOptions != null ) ? globalCodeEditorOptions . HighlightSymbol : default ( bool ) ;
289+ }
290+ set {
291+ if ( globalCodeEditorOptions != null ) {
292+ globalCodeEditorOptions . HighlightSymbol = value ;
293+ }
294+ }
295+ }
296+
297+ public bool EnableAnimations {
298+ get {
299+ return ( globalCodeEditorOptions != null ) ? globalCodeEditorOptions . EnableAnimations : default ( bool ) ;
300+ }
301+ set {
302+ if ( globalCodeEditorOptions != null ) {
303+ globalCodeEditorOptions . EnableAnimations = value ;
304+ }
305+ }
306+ }
307+
308+ public bool UseSmartIndentation {
309+ get {
310+ return ( globalCodeEditorOptions != null ) ? globalCodeEditorOptions . UseSmartIndentation : default ( bool ) ;
311+ }
312+ set {
313+ if ( globalCodeEditorOptions != null ) {
314+ globalCodeEditorOptions . UseSmartIndentation = value ;
315+ }
316+ }
317+ }
318+
319+ public bool EnableFolding {
320+ get {
321+ return ( globalCodeEditorOptions != null ) ? globalCodeEditorOptions . EnableFolding : default ( bool ) ;
322+ }
323+ set {
324+ if ( globalCodeEditorOptions != null ) {
325+ globalCodeEditorOptions . EnableFolding = value ;
326+ }
327+ }
328+ }
329+
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+ }
340+
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+ }
351+ }
93352}
0 commit comments