1 using Microsoft
.VisualStudio
.OLE
.Interop
;
2 using Microsoft
.VisualStudio
.TextManager
.Interop
;
3 using Microsoft
.VisualStudio
.Shell
.Interop
;
4 using Microsoft
.VisualStudio
.Designer
.Interfaces
;
5 using Microsoft
.VisualStudio
.Shell
;
8 using System
.Collections
;
9 using System
.ComponentModel
;
12 using System
.Diagnostics
;
13 using System
.Runtime
.InteropServices
;
14 using System
.Windows
.Forms
;
15 using Microsoft
.VisualStudio
;
16 using System
.Globalization
;
17 using IOleServiceProvider
= Microsoft
.VisualStudio
.OLE
.Interop
.IServiceProvider
;
18 using IServiceProvider
= System
.IServiceProvider
;
19 using VSRegistry
= Microsoft
.VisualStudio
.Shell
.VSRegistry
;
21 namespace Microsoft
.VisualStudio
.Package
{
22 /// <include file='doc\Utilities.uex' path='docs/doc[@for="IndentingStyle"]/*' />
23 public enum IndentingStyle
{
24 /// <include file='doc\Utilities.uex' path='docs/doc[@for="IndentingStyle.None"]/*' />
26 /// <include file='doc\Utilities.uex' path='docs/doc[@for="IndentingStyle.Block"]/*' />
28 /// <include file='doc\Utilities.uex' path='docs/doc[@for="IndentingStyle.Smart"]/*' />
32 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences"]/*' />
34 /// LanguagePreferences encapsulates the standard General and Tab settings for a language service
35 /// and provides a way of getting and setting the values. It is expected that you
36 /// will have one global LanguagePreferences created by your package. The General and Tabs
37 /// settings are automatically persisted in .vssettings files by the core editor package.
38 /// All you need to do is register your language under AutomationProperties/TextEditor
41 /// YourLanguage = s '%YourLocalizedName%'
43 /// val Name = s 'YourLanguage'
44 /// val Package = s '{F5E7E720-1401-11D1-883B-0000F87579D2}'
45 /// val ProfileSave = d 1
46 /// val ResourcePackage = s '%YourPackage%'
49 /// Therefore this class hides all it's properties from user setting persistence using
50 /// DesignerSerializationVisibility.Hidden. This is so that if you give this object
51 /// to the Package.ExportSettings method as the AutomationObject then it will only
52 /// write out your new settings which is what you want, otherwise the General and Tab
53 /// settings will appear in two places in the .vsssettings file.
55 [CLSCompliant(false),ComVisible(true), Guid("934a92fd-b63a-49c7-9284-11aec8c1e03f")]
56 public class LanguagePreferences
: IVsTextManagerEvents2
, IDisposable
{
57 IServiceProvider site
;
59 LANGPREFERENCES2 prefs
;
60 NativeMethods
.ConnectionPointCookie connection
;
62 bool enableMatchBraces
;
64 bool enableShowMatchingBrace
;
65 bool enableMatchBracesAtCaret
;
66 bool enableFormatSelection
;
67 bool enableCommenting
;
70 bool enableAsyncCompletion
;
73 _HighlightMatchingBraceFlags braceFlags
;
76 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.LanguagePreferences"]/*' />
78 /// Gets the language preferences.
80 public LanguagePreferences(IServiceProvider site
, Guid langSvc
, string name
) {
82 this.langSvc
= langSvc
;
86 /// <include file='doc\Preferences.uex' path='docs/doc[@for="LanguagePreferences.LanguagePreferences1"]/*' />
87 public LanguagePreferences() { }
89 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.LanguageName;"]/*' />
90 protected string LanguageName
{
91 get { return this.name; }
92 set { this.name = value; }
95 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.Site;"]/*' />
97 /// This property is not public for a reason. If it were public it would
98 /// get called during LoadSettingsFromStorage which will break it.
99 /// Instead use GetSite().
101 protected IServiceProvider Site
{
102 get { return this.site; }
103 set { this.site = value; }
106 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.Site;"]/*' />
107 public IServiceProvider
GetSite() {
111 // Our base language service perferences (from Babel originally)
112 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.EnableCodeSense;"]/*' />
113 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
114 public bool EnableCodeSense
{
115 get { return this.enableCodeSense; }
116 set { this.enableCodeSense = value; }
119 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.EnableMatchBraces;"]/*' />
120 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
121 public bool EnableMatchBraces
{
123 return this.enableMatchBraces
; }
124 set { this.enableMatchBraces = value; }
127 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.EnableQuickInfo;"]/*' />
128 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
129 public bool EnableQuickInfo
{
130 get { return this.enableQuickInfo; }
131 set { this.enableQuickInfo = value; }
134 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.EnableShowMatchingBrace;"]/*' />
135 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
136 public bool EnableShowMatchingBrace
{
137 get { return this.enableShowMatchingBrace; }
138 set { this.enableShowMatchingBrace = value; }
141 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.EnableMatchBracesAtCaret;"]/*' />
142 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
143 public bool EnableMatchBracesAtCaret
{
144 get { return this.enableMatchBracesAtCaret; }
145 set { this.enableMatchBracesAtCaret = value; }
148 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.MaxErrorMessages;"]/*' />
149 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
150 public int MaxErrorMessages
{
151 get { return this.maxErrorMessages; }
152 set { this.maxErrorMessages = value; }
155 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.CodeSenseDelay;"]/*' />
156 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
157 public int CodeSenseDelay
{
158 get { return this.codeSenseDelay; }
159 set { this.codeSenseDelay = value; }
162 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.EnableAsyncCompletion;"]/*' />
163 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
164 public bool EnableAsyncCompletion
{
165 get { return this.enableAsyncCompletion; }
166 set { this.enableAsyncCompletion = value; }
169 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.EnableFormatSelection;"]/*' />
170 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
171 public bool EnableFormatSelection
{
172 get { return this.enableFormatSelection; }
173 set { this.enableFormatSelection = value; }
176 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.EnableCommenting;"]/*' />
177 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
178 public bool EnableCommenting
{
179 get { return this.enableCommenting; }
180 set { this.enableCommenting = value; }
183 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.MaxRegionTime;"]/*' />
184 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
185 public int MaxRegionTime
{
186 get { return this.maxRegionTime; }
187 set { this.maxRegionTime = value; }
190 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.HighlightMatchingBraceFlags;"]/*' />
191 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
192 public _HighlightMatchingBraceFlags HighlightMatchingBraceFlags
{
193 get { return this.braceFlags; }
194 set { this.braceFlags = value; }
197 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.Init"]/*' />
198 public virtual void Init() {
199 using (RegistryKey key
= VSRegistry
.RegistryRoot(__VsLocalRegistryType
.RegType_Configuration
)) {
201 InitMachinePreferences(key
, name
);
204 using (RegistryKey key
= VSRegistry
.RegistryRoot(__VsLocalRegistryType
.RegType_UserSettings
)) {
206 InitUserPreferences(key
, name
);
212 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.InitUserPreferences"]/*' />
213 public virtual void InitUserPreferences(RegistryKey key
, string name
) {
214 this.GetLanguagePreferences();
216 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.GetIntegerValue"]/*' />
217 public int GetIntegerValue(RegistryKey key
, string name
, int def
) {
218 object o
= key
.GetValue(name
);
219 if (o
is int) return (int)o
;
221 if (o
is string && int.TryParse((string)o
,NumberStyles
.Integer
, CultureInfo
.InvariantCulture
, out result
))
225 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.GetBooleanValue"]/*' />
226 public bool GetBooleanValue(RegistryKey key
, string name
, bool def
) {
227 object o
= key
.GetValue(name
);
228 if (o
is int) return ((int)o
!= 0);
230 if (o
is string && bool.TryParse((string)o
,out result
))
235 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.InitMachinePreferences"]/*' />
236 public virtual void InitMachinePreferences(RegistryKey key
, string name
)
238 using (RegistryKey keyLanguage
= key
.OpenSubKey("languages\\language services\\" + name
, false))
240 if (keyLanguage
!= null) {
241 this.EnableCodeSense
= GetBooleanValue(keyLanguage
, "CodeSense", true);
242 this.EnableMatchBraces
= GetBooleanValue(keyLanguage
, "MatchBraces", true);
243 this.EnableQuickInfo
= GetBooleanValue(keyLanguage
, "QuickInfo", true);
244 this.EnableShowMatchingBrace
= GetBooleanValue(keyLanguage
, "ShowMatchingBrace", true);
245 this.EnableMatchBracesAtCaret
= GetBooleanValue(keyLanguage
, "MatchBracesAtCaret", true);
246 this.MaxErrorMessages
= GetIntegerValue(keyLanguage
, "MaxErrorMessages", 10);
247 this.CodeSenseDelay
= GetIntegerValue(keyLanguage
, "CodeSenseDelay", 1000);
248 this.EnableAsyncCompletion
= GetBooleanValue(keyLanguage
, "EnableAsyncCompletion", true);
249 this.EnableFormatSelection
= GetBooleanValue(keyLanguage
, "EnableFormatSelection", false);
250 this.EnableCommenting
= GetBooleanValue(keyLanguage
, "EnableCommenting", true);
251 this.AutoOutlining
= GetBooleanValue(keyLanguage
, "AutoOutlining", true);
252 this.MaxRegionTime
= GetIntegerValue(keyLanguage
, "MaxRegionTime", 2000); // 2 seconds
253 this.braceFlags
= (_HighlightMatchingBraceFlags
)GetIntegerValue(keyLanguage
, "HighlightMatchingBraceFlags", (int)_HighlightMatchingBraceFlags
.HMB_USERECTANGLEBRACES
);
258 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.Dispose"]/*' />
259 public virtual void Dispose() {
265 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.AutoListMembers"]/*' />
266 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
267 public bool AutoListMembers
{
268 get { return prefs.fAutoListMembers != 0; }
269 set { prefs.fAutoListMembers = (uint)(value ? 1 : 0); }
272 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.HideAdvancedMembers"]/*' />
273 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
274 public bool HideAdvancedMembers
{
275 get { return prefs.fHideAdvancedAutoListMembers != 0; }
276 set { prefs.fHideAdvancedAutoListMembers = (uint)(value ? 1 : 0); }
279 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.ParameterInformation"]/*' />
280 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
281 public bool ParameterInformation
{
282 get { return prefs.fAutoListParams != 0; }
283 set { prefs.fAutoListParams = (uint)(value ? 1 : 0); }
286 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.VirtualSpace"]/*' />
287 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
288 public bool VirtualSpace
{
289 get { return prefs.fVirtualSpace != 0; }
290 set { prefs.fVirtualSpace = (uint)(value ? 1 : 0); }
293 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.WordWrap"]/*' />
294 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
295 public bool WordWrap
{
296 get { return prefs.fWordWrap != 0; }
297 set { prefs.fWordWrap = (uint)(value ? 1 : 0); }
300 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.WordWrapGlyphs"]/*' />
301 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
302 public bool WordWrapGlyphs
{
303 get { return (int)prefs.fWordWrapGlyphs != 0; }
304 set { prefs.fWordWrapGlyphs = (uint)(value ? 1 : 0); }
307 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.CutCopyBlankLines"]/*' />
308 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
309 public bool CutCopyBlankLines
{
310 get { return (int)prefs.fCutCopyBlanks != 0; }
311 set { prefs.fCutCopyBlanks = (uint)(value ? 1 : 0); }
314 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.LineNumbers"]/*' />
315 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
316 public bool LineNumbers
{
317 get { return prefs.fLineNumbers != 0; }
318 set { prefs.fLineNumbers = (uint)(value ? 1 : 0); }
321 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.EnableLeftClickForURLs"]/*' />
322 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
323 public bool EnableLeftClickForURLs
{
324 get { return prefs.fHotURLs != 0; }
325 set { prefs.fHotURLs = (uint)(value ? 1 : 0); }
329 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.Indenting"]/*' />
330 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
331 public IndentingStyle IndentStyle
{
332 get { return (IndentingStyle)prefs.IndentStyle; }
333 set { prefs.IndentStyle = (vsIndentStyle)value; }
336 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.TabSize"]/*' />
337 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
339 get { return (int)prefs.uTabSize; }
340 set { prefs.uTabSize = (uint)value; }
343 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.IndentSize"]/*' />
344 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
345 public int IndentSize
{
346 get { return (int)prefs.uIndentSize; }
347 set { prefs.uIndentSize = (uint)value; }
350 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.InsertSpaces"]/*' />
351 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
352 public bool InsertTabs
{
353 get { return prefs.fInsertTabs != 0; }
354 set { prefs.fInsertTabs = (uint)(value ? 1 : 0); }
357 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.ShowNavigationBar"]/*' />
358 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
359 public bool ShowNavigationBar
{
360 get { return (int)prefs.fDropdownBar != 0; }
361 set { prefs.fDropdownBar = (uint)(value ? 1 : 0); }
364 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.EnableAutoOutlining"]/*' />
365 public bool AutoOutlining
{
366 get { return this.autoOutlining; }
367 set { this.autoOutlining = value; }
370 /// <include file='doc\Preferences.uex' path='docs/doc[@for="LanguagePreferences.GetLanguagePrefs"]/*' />
371 public virtual void GetLanguagePreferences() {
372 IVsTextManager textMgr
= site
.GetService(typeof(SVsTextManager
)) as IVsTextManager
;
373 if (textMgr
!= null) {
374 this.prefs
.guidLang
= langSvc
;
375 IVsTextManager2 textMgr2
= site
.GetService(typeof(SVsTextManager
)) as IVsTextManager2
;
376 if (textMgr
!= null) {
377 LANGPREFERENCES2
[] langPrefs2
= new LANGPREFERENCES2
[1];
378 langPrefs2
[0] = this.prefs
;
379 if (NativeMethods
.Succeeded(textMgr2
.GetUserPreferences2(null, null, langPrefs2
, null))) {
380 this.prefs
= langPrefs2
[0];
382 Debug
.Assert(false, "textMgr2.GetUserPreferences2");
388 /// <include file='doc\PropertySheet.uex' path='docs/doc[@for="LanguagePreferences.Apply"]/*' />
389 public virtual void Apply() {
390 IVsTextManager2 textMgr2
= site
.GetService(typeof(SVsTextManager
)) as IVsTextManager2
;
391 if (textMgr2
!= null) {
392 this.prefs
.guidLang
= langSvc
;
393 LANGPREFERENCES2
[] langPrefs2
= new LANGPREFERENCES2
[1];
394 langPrefs2
[0] = this.prefs
;
395 if (!NativeMethods
.Succeeded(textMgr2
.SetUserPreferences2(null, null, langPrefs2
, null))) {
396 Debug
.Assert(false, "textMgr2.SetUserPreferences2");
401 private void Connect() {
402 if (this.connection
== null && this.site
!= null) {
403 IVsTextManager2 textMgr2
= this.site
.GetService(typeof(SVsTextManager
)) as IVsTextManager2
;
404 if (textMgr2
!= null) {
405 this.connection
= new NativeMethods
.ConnectionPointCookie(textMgr2
, (IVsTextManagerEvents2
)this, typeof(IVsTextManagerEvents2
));
410 private void Disconnect() {
411 if (this.connection
!= null) {
412 this.connection
.Dispose();
413 this.connection
= null;
417 #region IVsTextManagerEvents2 Members
419 /// <include file='doc\Preferences.uex' path='docs/doc[@for="LanguagePreferences.OnRegisterMarkerType"]/*' />
420 public virtual int OnRegisterMarkerType(int iMarkerType
)
422 return NativeMethods
.S_OK
;
424 /// <include file='doc\Preferences.uex' path='docs/doc[@for="LanguagePreferences.OnRegisterView"]/*' />
425 public virtual int OnRegisterView(IVsTextView view
)
427 return NativeMethods
.S_OK
;
429 /// <include file='doc\Preferences.uex' path='docs/doc[@for="LanguagePreferences.OnUnregisterView"]/*' />
430 public virtual int OnUnregisterView(IVsTextView view
)
432 return NativeMethods
.S_OK
;
434 /// <include file='doc\Preferences.uex' path='docs/doc[@for="LanguagePreferences.OnReplaceAllInFilesBegin"]/*' />
435 public virtual int OnReplaceAllInFilesBegin()
437 return NativeMethods
.S_OK
;
439 /// <include file='doc\Preferences.uex' path='docs/doc[@for="LanguagePreferences.OnReplaceAllInFilesEnd"]/*' />
440 public virtual int OnReplaceAllInFilesEnd()
442 return NativeMethods
.S_OK
;
445 /// <include file='doc\Preferences.uex' path='docs/doc[@for="LanguagePreferences.OnUserPreferencesChanged2"]/*' />
446 public virtual int OnUserPreferencesChanged2(VIEWPREFERENCES2
[] viewPrefs
, FRAMEPREFERENCES2
[] framePrefs
, LANGPREFERENCES2
[] langPrefs
, FONTCOLORPREFERENCES2
[] fontColorPrefs
)
448 if (langPrefs
!= null && langPrefs
.Length
> 0 && langPrefs
[0].guidLang
== this.langSvc
) {
449 this.prefs
= langPrefs
[0];
451 return NativeMethods
.S_OK
;