-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add sample for Settings API --------- Co-authored-by: Charles Willis <[email protected]>
- Loading branch information
Showing
10 changed files
with
459 additions
and
0 deletions.
There are no files selected for viewing
14 changes: 14 additions & 0 deletions
14
New_Extensibility_Model/Samples/SettingsSample/.vsextension/string-resources.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"SettingsSample.MyToolWindowCommand.DisplayName": "Sample Text Tool Window", | ||
"SettingsSample.Settings.Category.DisplayName": "Settings Sample", | ||
"SettingsSample.Settings.Category.Description": "Settings for the LoremIpsum sample generator.", | ||
"SettingsSample.Settings.AutoUpdate.DisplayName": "Auto Update", | ||
"SettingsSample.Settings.AutoUpdate.Description": "Whether to update the sample text when a setting changes.", | ||
"SettingsSample.Settings.TextLength.DisplayName": "Text Length", | ||
"SettingsSample.Settings.TextLength.Description": "Number of characters to include in the generated text.", | ||
"SettingsSample.Settings.QuoteStyle.DisplayName": "Quote Style", | ||
"SettingsSample.Settings.QuoteStyle.Description": "Style of quotes to enclose the generated text.", | ||
"SettingsSample.Settings.QuoteStyle.None": "None", | ||
"SettingsSample.Settings.QuoteStyle.Single": "Single", | ||
"SettingsSample.Settings.QuoteStyle.Double": "Double" | ||
} |
47 changes: 47 additions & 0 deletions
47
New_Extensibility_Model/Samples/SettingsSample/MyToolWindow.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
namespace SettingsSample; | ||
|
||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.VisualStudio.Extensibility; | ||
using Microsoft.VisualStudio.Extensibility.ToolWindows; | ||
using Microsoft.VisualStudio.RpcContracts.RemoteUI; | ||
|
||
/// <summary> | ||
/// A sample tool window. | ||
/// </summary> | ||
[VisualStudioContribution] | ||
public class MyToolWindow : ToolWindow | ||
{ | ||
private MyToolWindowData? dataContext; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="MyToolWindow" /> class. | ||
/// </summary> | ||
public MyToolWindow() | ||
{ | ||
this.Title = "Settings Sample Tool Window"; | ||
} | ||
|
||
/// <inheritdoc /> | ||
public override ToolWindowConfiguration ToolWindowConfiguration => new() | ||
{ | ||
Placement = ToolWindowPlacement.DocumentWell, | ||
AllowAutoCreation = false, | ||
}; | ||
|
||
/// <inheritdoc /> | ||
public override Task InitializeAsync(CancellationToken cancellationToken) | ||
{ | ||
this.dataContext = new MyToolWindowData(this.Extensibility); | ||
return this.dataContext.InitializeAsync(cancellationToken); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public override Task<IRemoteUserControl> GetContentAsync(CancellationToken cancellationToken) | ||
{ | ||
return Task.FromResult<IRemoteUserControl>(new MyToolWindowControl(this.dataContext)); | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
New_Extensibility_Model/Samples/SettingsSample/MyToolWindowCommand.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
namespace SettingsSample; | ||
|
||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.VisualStudio.Extensibility; | ||
using Microsoft.VisualStudio.Extensibility.Commands; | ||
|
||
/// <summary> | ||
/// A sample command for showing a tool window. | ||
/// </summary> | ||
[VisualStudioContribution] | ||
public class MyToolWindowCommand : Command | ||
{ | ||
/// <inheritdoc /> | ||
public override CommandConfiguration CommandConfiguration => new("%SettingsSample.MyToolWindowCommand.DisplayName%") | ||
{ | ||
Placements = [CommandPlacement.KnownPlacements.ToolsMenu], | ||
Icon = new(ImageMoniker.KnownValues.ToolWindow, IconSettings.IconAndText), | ||
}; | ||
|
||
/// <inheritdoc /> | ||
public override async Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken) | ||
{ | ||
await this.Extensibility.Shell().ShowToolWindowAsync<MyToolWindow>(activate: true, cancellationToken); | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
New_Extensibility_Model/Samples/SettingsSample/MyToolWindowControl.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
namespace SettingsSample; | ||
|
||
using System.Threading; | ||
using Microsoft.VisualStudio.Extensibility.UI; | ||
|
||
/// <summary> | ||
/// A sample remote user control to use as tool window UI content. | ||
/// </summary> | ||
internal class MyToolWindowControl : RemoteUserControl | ||
{ | ||
/// <summary> | ||
/// Initializes a new instance of the <see cref="MyToolWindowControl" /> class. | ||
/// </summary> | ||
/// <param name="dataContext"> | ||
/// Data context of the remote control which can be referenced from xaml through data binding. | ||
/// </param> | ||
public MyToolWindowControl(object? dataContext) | ||
: base(dataContext) | ||
{ | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
New_Extensibility_Model/Samples/SettingsSample/MyToolWindowControl.xaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<DataTemplate xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
xmlns:vs="http://schemas.microsoft.com/visualstudio/extensibility/2022/xaml" | ||
xmlns:styles="clr-namespace:Microsoft.VisualStudio.Shell;assembly=Microsoft.VisualStudio.Shell.15.0" | ||
xmlns:colors="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Shell.15.0"> | ||
<Border Background="{DynamicResource {x:Static colors:EnvironmentColors.ToolWindowBackgroundBrushKey}}" | ||
TextElement.Foreground="{DynamicResource {x:Static colors:EnvironmentColors.ToolWindowTextBrushKey}}" | ||
Padding="5"> | ||
<StackPanel Orientation="Vertical" | ||
HorizontalAlignment="Center" | ||
VerticalAlignment="Center"> | ||
<TextBlock Margin="0,0,5,0" | ||
Text="Sample Text:" | ||
VerticalAlignment="Center" /> | ||
<TextBlock x:Name="SampleTextBlock" | ||
HorizontalAlignment="Center" | ||
VerticalAlignment="Center" | ||
Text="{Binding SampleText, Mode=OneWay}" | ||
Style="{StaticResource {x:Static styles:VsResourceKeys.TextBlockEnvironment155PercentFontSizeStyleKey}}"> | ||
</TextBlock> | ||
<Button x:Name="UpdateButton" | ||
Content="Update Sample Text From Settings" | ||
IsEnabled="{Binding ManualUpdate}" | ||
Margin="0,10,0,0" | ||
MinHeight="25" | ||
MinWidth="60" | ||
Style="{StaticResource {x:Static styles:VsResourceKeys.ButtonStyleKey}}" | ||
Command="{Binding UpdateCommand}" /> | ||
</StackPanel> | ||
</Border> | ||
</DataTemplate> |
139 changes: 139 additions & 0 deletions
139
New_Extensibility_Model/Samples/SettingsSample/MyToolWindowData.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
namespace SettingsSample; | ||
|
||
using System; | ||
using System.Runtime.Serialization; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft; | ||
using Microsoft.VisualStudio.Extensibility; | ||
using Microsoft.VisualStudio.Extensibility.Settings; | ||
using Microsoft.VisualStudio.Extensibility.UI; | ||
|
||
/// <summary> | ||
/// A sample data context object to use with tool window UI content. | ||
/// </summary> | ||
[DataContract] | ||
internal class MyToolWindowData : NotifyPropertyChangedObject | ||
{ | ||
internal static readonly string LoremIpsumText = """ | ||
Lorem ipsum dolor sit amet consectetur adipiscing elit dignissim lacinia donec, | ||
praesent diam ac mattis morbi nisi dictum dapibus. Convallis natoque interdum | ||
curabitur malesuada tellus aliquam dignissim hendrerit tempor, primis sem nulla | ||
neque cubilia rutrum mollis nisl, eleifend imperdiet lacinia fames gravida sed mus | ||
magnis. Pretium aliquet consequat curabitur eros eleifend praesent, nostra malesuada | ||
hendrerit ornare volutpat, cubilia aptent at mollis convallis. | ||
"""; | ||
|
||
private readonly VisualStudioExtensibility extensibility; | ||
private string sampleText = LoremIpsumText; | ||
private bool manualUpdate = false; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="MyToolWindowData" /> class. | ||
/// </summary> | ||
/// <param name="extensibility"> | ||
/// Extensibility object instance. | ||
/// </param> | ||
public MyToolWindowData(VisualStudioExtensibility extensibility) | ||
{ | ||
this.extensibility = Requires.NotNull(extensibility, nameof(extensibility)); | ||
|
||
this.UpdateCommand = new AsyncCommand(this.UpdateAsync); | ||
} | ||
|
||
/// <summary> | ||
/// Gets the async command used to show a message prompt. | ||
/// </summary> | ||
[DataMember] | ||
public IAsyncCommand UpdateCommand | ||
{ | ||
get; | ||
} | ||
|
||
/// <summary> | ||
/// Gets or sets a value indicating whether the user must | ||
/// click the "Update" button to refresh the sample text. | ||
/// </summary> | ||
[DataMember] | ||
public bool ManualUpdate | ||
{ | ||
get => this.manualUpdate; | ||
set => this.SetProperty(ref this.manualUpdate, value); | ||
} | ||
|
||
/// <summary> | ||
/// Gets or sets the message to display in the message prompt. | ||
/// </summary> | ||
[DataMember] | ||
public string SampleText | ||
{ | ||
get => this.sampleText; | ||
set => this.SetProperty(ref this.sampleText, value); | ||
} | ||
|
||
/// <summary> | ||
/// Initializes the current instance of <see cref="MyToolWindowData"/>. | ||
/// </summary> | ||
/// <param name="cancellationToken">Cancellation token to monitor.</param> | ||
/// <returns>Task indicating completion of initialization.</returns> | ||
public Task InitializeAsync(CancellationToken cancellationToken) | ||
{ | ||
return this.InitializeSettingsAsync(cancellationToken); | ||
} | ||
|
||
#pragma warning disable VSEXTPREVIEW_SETTINGS // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. | ||
|
||
private async Task InitializeSettingsAsync(CancellationToken cancellationToken) | ||
{ | ||
await this.extensibility.Settings().SubscribeAsync( | ||
[SettingDefinitions.SettingsSampleCategory], | ||
cancellationToken, | ||
values => | ||
{ | ||
if (values.TryGetValue(SettingDefinitions.AutoUpdateSetting.FullId, out ISettingValue? autoUpdateValue)) | ||
{ | ||
this.ManualUpdate = !autoUpdateValue.Value<bool>(); | ||
} | ||
|
||
if (!this.ManualUpdate) | ||
{ | ||
this.UpdateSampleTextFromSettings(values); | ||
} | ||
}); | ||
} | ||
|
||
private async Task UpdateAsync(object? commandParameter, CancellationToken cancellationToken) | ||
{ | ||
SettingValues values = await this.extensibility.Settings().ReadEffectiveValuesAsync( | ||
[SettingDefinitions.SettingsSampleCategory], | ||
cancellationToken); | ||
|
||
this.UpdateSampleTextFromSettings(values); | ||
} | ||
|
||
private void UpdateSampleTextFromSettings(SettingValues values) | ||
{ | ||
string text = LoremIpsumText; | ||
|
||
if (values.TryGetValue(SettingDefinitions.TextLengthSetting.FullId, out ISettingValue? textLengthValue)) | ||
{ | ||
int length = textLengthValue.Value<int>(); | ||
text = LoremIpsumText[..Math.Min(length, LoremIpsumText.Length)]; | ||
} | ||
|
||
if (values.TryGetValue(SettingDefinitions.QuoteStyleSetting.FullId, out ISettingValue? quoteStyleValue)) | ||
{ | ||
this.SampleText = quoteStyleValue.Value<string>() switch | ||
{ | ||
"single" => $"'{text}'", | ||
"double" => $"\"{text}\"", | ||
_ => text, | ||
}; | ||
} | ||
} | ||
|
||
#pragma warning restore VSEXTPREVIEW_SETTINGS // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
--- | ||
title: Extension Settings Sample reference | ||
description: A reference sample for extensions settings | ||
date: 2024-08-20 | ||
--- | ||
|
||
# Walkthrough: Extension Settings Sample | ||
|
||
This is a simple extension that shows how settings can be added to Visual Studio and read to configure the behavior of a tool window. | ||
|
||
## Tool window definition | ||
|
||
See the [ToolWindowSample](../ToolWindowSample/README.md) for more information on defining the tool window. | ||
|
||
## Setting definitions | ||
|
||
The extension contains a [code file](./SettingDefinitions.cs) that defines three settings and a parent category to contain them. Each setting and the category starts with the `VisualStudioContribution` class attribute which makes it available to Visual Studio: | ||
|
||
```csharp | ||
[VisualStudioContribution] | ||
internal static SettingCategory SettingsSampleCategory { get; } = new("settingsSample", "%SettingsSample.Settings.Category.DisplayName%") | ||
{ | ||
Description = "%SettingsSample.Settings.Category.Description%", | ||
}; | ||
``` | ||
|
||
```csharp | ||
[VisualStudioContribution] | ||
internal static Setting.Boolean AutoUpdateSetting { get; } = new("autoUpdate", "%SettingsSample.Settings.AutoUpdate.DisplayName%", SettingsSampleCategory, defaultValue: true) | ||
{ | ||
Description = "%SettingsSample.Settings.AutoUpdate.Description%", | ||
}; | ||
|
||
The `SettingCategory` and `Setting.Boolean` properties define information about the settings that is available to Visual Studio even before the extension is loaded. | ||
|
||
In `MyToolWindowData`, a subscription is created to read and monitor value changes for all the settings in the `SettingSampleCategory`: | ||
|
||
```csharp | ||
public MyToolWindowData(VisualStudioExtensibility extensibility) | ||
{ | ||
... | ||
this.InitializeSettingsAsync(extensibility).Forget(); | ||
} | ||
private async Task InitializeSettingsAsync(VisualStudioExtensibility extensibility) | ||
{ | ||
await extensibility.Settings().SubscribeAsync( | ||
[SettingDefinitions.SettingsSampleCategory], | ||
CancellationToken.None, | ||
values => {...}); | ||
} | ||
``` | ||
|
||
## Usage | ||
|
||
Once deployed, the "Sample Text Tool Window" command can be used to show the "Settings Sample Tool Window" in the document well. | ||
|
||
### Changing the TextLengthSetting | ||
|
||
Setting values are stored in json files in well-known locations. After deploying the extension: | ||
|
||
* Open the "Sample Text Tool Window": Tools -> Sample Text Tool Window | ||
* Open the extension settings json file: Extensions -> Extension Settings (experimental) -> User Scope (current install) | ||
|
||
The `extensibility.settings.json` file will open in an editor. To change the textLength setting, add a value to the file to override | ||
the default: | ||
|
||
```json | ||
/* Visual Studio Settings File */ | ||
{ | ||
"settingsSample.textLength": 150 | ||
} | ||
``` | ||
|
||
The string key is the `FullId` property of the `TextLengthSetting` property defined in [SettingDefinitions](./SettingDefinitions.cs). It is formed by the id of the category and the id of the setting. | ||
|
||
Each time you change the value and save the file, the sample text in the tool window will update. | ||
|
||
## Current Limitations | ||
|
||
The settings API is currently experimental, and has several limitations: | ||
|
||
* An extension can only read or write settings from itself or other extensions. Core Visual Studio settings are not available. | ||
* There is no UI for extension settings. They can only be changed by using the json files available in the Extensions -> Extension Settings (experimental) menu. |
Oops, something went wrong.