Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
Piedone committed May 9, 2020
2 parents b9fd2ac + 513fd2c commit ecf043d
Show file tree
Hide file tree
Showing 15 changed files with 199 additions and 149 deletions.
17 changes: 7 additions & 10 deletions Lombiq.Vsix.Orchard/Commands/InjectDependencyCommand.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using EnvDTE;
using Lombiq.Vsix.Orchard.Constants;
using Lombiq.Vsix.Orchard.Constants;
using Lombiq.Vsix.Orchard.Forms;
using Lombiq.Vsix.Orchard.Helpers;
using Lombiq.Vsix.Orchard.Services.DependencyInjector;
Expand All @@ -18,7 +17,6 @@ internal sealed class InjectDependencyCommand
public static readonly Guid CommandSet = PackageGuids.LombiqOrchardVisualStudioExtensionCommandSetGuid;

private readonly AsyncPackage _package;
private readonly DTE _dte;
private readonly IDependencyInjector _dependencyInjector;
private readonly IEnumerable<IFieldNameFromDependencyGenerator> _fieldNameGenerators;
private readonly IEnumerable<IDependencyNameProvider> _dependencyNameProviders;
Expand All @@ -28,13 +26,11 @@ internal sealed class InjectDependencyCommand

private InjectDependencyCommand(
AsyncPackage package,
DTE dte,
IDependencyInjector dependencyInjector,
IEnumerable<IFieldNameFromDependencyGenerator> fieldNameGenerators,
IEnumerable<IDependencyNameProvider> dependencyNameProviders)
{
_package = package;
_dte = dte;
_dependencyInjector = dependencyInjector;
_fieldNameGenerators = fieldNameGenerators;
_dependencyNameProviders = dependencyNameProviders;
Expand All @@ -45,7 +41,6 @@ public static async Task Create(AsyncPackage package)
{
Instance = Instance ?? new InjectDependencyCommand(
package,
package.GetDte(),
await package.GetServiceAsync<IDependencyInjector>(),
await package.GetServicesAsync<IFieldNameFromDependencyGenerator>(),
await package.GetServicesAsync<IDependencyNameProvider>());
Expand All @@ -54,18 +49,20 @@ await package.GetServicesAsync<IFieldNameFromDependencyGenerator>(),

public async Task InitializeUI()
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
(await _package.GetServiceAsync<IMenuCommandService>()).AddCommand(
new MenuCommand(
MenuItemCallback,
new CommandID(CommandSet, CommandId)));
}


private void MenuItemCallback(object sender, EventArgs e)
private async void MenuItemCallback(object sender, EventArgs e)
{
var injectDependencyCaption = "Inject Dependency";
var dte = await _package.GetDteAsync();

if (_dte.ActiveDocument == null)
if (dte.ActiveDocument == null)
{
DialogHelpers.Error("Open a code file first.", injectDependencyCaption);

Expand All @@ -75,7 +72,7 @@ private void MenuItemCallback(object sender, EventArgs e)
using (var injectDependencyDialog = new InjectDependencyDialog(
_fieldNameGenerators,
_dependencyNameProviders,
_dependencyInjector.GetExpectedClassName(_dte.ActiveDocument)))
_dependencyInjector.GetExpectedClassName(dte.ActiveDocument)))
{
if (injectDependencyDialog.ShowDialog() == DialogResult.OK)
{
Expand All @@ -92,7 +89,7 @@ private void MenuItemCallback(object sender, EventArgs e)
}

var result = _dependencyInjector.Inject(
_dte.ActiveDocument,
dte.ActiveDocument,
injectDependencyDialog.GetDependencyInjectionData());

if (!result.Success)
Expand Down
91 changes: 49 additions & 42 deletions Lombiq.Vsix.Orchard/Commands/OpenErrorLogCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Lombiq.Vsix.Orchard.Services.LogWatcher;
using Microsoft.VisualStudio.CommandBars;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Threading;
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
Expand All @@ -13,35 +14,32 @@

namespace Lombiq.Vsix.Orchard.Commands
{
internal sealed class OpenErrorLogCommand : IDisposable
internal sealed class OpenErrorLogCommand : IAsyncDisposable
{
public const int CommandId = CommandIds.OpenErrorLogCommandId;
public static readonly Guid CommandSet = PackageGuids.LombiqOrchardVisualStudioExtensionCommandSetGuid;


private readonly AsyncPackage _package;
private readonly DTE _dte;
private readonly Lazy<ILogWatcherSettings> _lazyLogWatcherSettings;
private readonly ILogWatcherSettingsAccessor _logWatcherSettingsAccessor;
private readonly IEnumerable<ILogFileWatcher> _logWatchers;
private readonly IBlinkStickManager _blinkStickManager;
private readonly object _settingsChangeLock = new object();

private OleMenuCommand _openErrorLogCommand;
private CommandBar _orchardLogWatcherToolbar;
private bool _hasSeenErrorLogUpdate;
private bool _errorIndicatorStateChanged;
private ILogFileStatus _latestUpdatedLogFileStatus;


private OpenErrorLogCommand(
AsyncPackage package,
DTE dte,
Lazy<ILogWatcherSettings> lazyLogWatcherSettings,
ILogWatcherSettingsAccessor logWatcherSettingsAccessor,
IEnumerable<ILogFileWatcher> logWatchers,
IBlinkStickManager blinkStickManager)
{
_package = package;
_dte = dte;
_lazyLogWatcherSettings = lazyLogWatcherSettings;
_logWatcherSettingsAccessor = logWatcherSettingsAccessor;
_logWatchers = logWatchers;
_blinkStickManager = blinkStickManager;
}
Expand All @@ -53,29 +51,28 @@ public static async Task Create(AsyncPackage package, ILogWatcherSettingsAccesso
{
Instance = Instance ?? new OpenErrorLogCommand(
package,
package.GetDte(),
new Lazy<ILogWatcherSettings>(logWatcherSettingsAccessor.GetSettings),
logWatcherSettingsAccessor,
await package.GetServicesAsync<ILogFileWatcher>(),
await package.GetServiceAsync<IBlinkStickManager>());

Instance.InitalizeWatchers();
await Instance.InitalizeWatchers();
}


public async Task InitializeUI()
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

_openErrorLogCommand = new OleMenuCommand(OpenErrorLogCallback, new CommandID(CommandSet, CommandId));
_openErrorLogCommand.BeforeQueryStatus += OpenErrorLogCommandBeforeQueryStatusCallback;
_openErrorLogCommand.Enabled = false;

(await _package.GetServiceAsync<IMenuCommandService>()).AddCommand(_openErrorLogCommand);

// Store Log Watcher toolbar in a variable to be able to show or hide depending on the Log Watcher settings.
_orchardLogWatcherToolbar = ((CommandBars)_dte.CommandBars)[CommandBarNames.OrchardLogWatcherToolbarName];

if (_lazyLogWatcherSettings.Value.LogWatcherEnabled) _openErrorLogCommand.Visible = true;
if ((await _logWatcherSettingsAccessor.GetSettings()).LogWatcherEnabled) _openErrorLogCommand.Visible = true;
}

public void Dispose()
public async Task DisposeAsync()
{
_blinkStickManager.Dispose();

Expand All @@ -85,11 +82,11 @@ public void Dispose()
watcher.Dispose();
}

_lazyLogWatcherSettings.Value.SettingsUpdated -= LogWatcherSettingsUpdatedCallback;
(await _logWatcherSettingsAccessor.GetSettings()).SettingsUpdated -= LogWatcherSettingsUpdatedCallback;
}


private void InitalizeWatchers()
private async Task InitalizeWatchers()
{
_hasSeenErrorLogUpdate = true;
_errorIndicatorStateChanged = true;
Expand All @@ -99,23 +96,24 @@ private void InitalizeWatchers()
watcher.LogUpdated += LogFileUpdatedCallback;
}

_lazyLogWatcherSettings.Value.SettingsUpdated += LogWatcherSettingsUpdatedCallback;
var settings = await _logWatcherSettingsAccessor.GetSettings();
settings.SettingsUpdated += LogWatcherSettingsUpdatedCallback;

if (_lazyLogWatcherSettings.Value.LogWatcherEnabled) StartLogFileWatching();
if (settings.LogWatcherEnabled) StartLogFileWatching();
}

private void OpenErrorLogCommandBeforeQueryStatusCallback(object sender, EventArgs e) =>
UpdateOpenErrorLogCommandAccessibilityAndText();
private async void OpenErrorLogCommandBeforeQueryStatusCallback(object sender, EventArgs e) =>
await UpdateOpenErrorLogCommandAccessibilityAndText();

private void LogFileUpdatedCallback(object sender, LogChangedEventArgs context)
private async void LogFileUpdatedCallback(object sender, LogChangedEventArgs context)
{
_hasSeenErrorLogUpdate = !context.LogFileStatus.HasContent;
_latestUpdatedLogFileStatus = context.LogFileStatus;

UpdateOpenErrorLogCommandAccessibilityAndText(context.LogFileStatus);
await UpdateOpenErrorLogCommandAccessibilityAndText(context.LogFileStatus);
}

private void OpenErrorLogCallback(object sender, EventArgs e)
private async void OpenErrorLogCallback(object sender, EventArgs e)
{
_hasSeenErrorLogUpdate = true;

Expand All @@ -128,37 +126,47 @@ private void OpenErrorLogCallback(object sender, EventArgs e)
DialogHelpers.Error("The log file doesn't exist.", "Open Orchard Error Log");
}

UpdateOpenErrorLogCommandAccessibilityAndText();
await UpdateOpenErrorLogCommandAccessibilityAndText();
}

private void LogWatcherSettingsUpdatedCallback(object sender, LogWatcherSettingsUpdatedEventArgs e)
private async void LogWatcherSettingsUpdatedCallback(object sender, LogWatcherSettingsUpdatedEventArgs e)
{
_orchardLogWatcherToolbar.Visible = e.Settings.LogWatcherEnabled;
var isEnabled = e.Settings.LogWatcherEnabled;
var orchardLogWatcherToolbar = ((CommandBars)(await _package.GetDteAsync()).CommandBars)[CommandBarNames.OrchardLogWatcherToolbarName];
orchardLogWatcherToolbar.Visible = isEnabled;

if (!e.Settings.LogWatcherEnabled)
{
StopLogFileWatching();
}
else
// Since this method will be called from the UI thread not blocking it with the watcher changes that can
// potentially take some time.
await Task.Run(() =>
{
StartLogFileWatching();
}
// If the settings are repeatedly change then wait for the first one to finish before starting the next.
lock (_settingsChangeLock)
{
if (isEnabled)
{
StartLogFileWatching();
}
else
{
StopLogFileWatching();
}
}
});

UpdateOpenErrorLogCommandAccessibilityAndText();
await UpdateOpenErrorLogCommandAccessibilityAndText();
}

private void UpdateOpenErrorLogCommandAccessibilityAndText(ILogFileStatus logFileStatus = null)
private async Task UpdateOpenErrorLogCommandAccessibilityAndText(ILogFileStatus logFileStatus = null)
{
var logWatcherSettings = _lazyLogWatcherSettings.Value;
var logWatcherSettings = await _logWatcherSettingsAccessor.GetSettings();

if (!_dte.Solution.IsOpen)
if (!(await _package.GetDteAsync()).SolutionIsOpen())
{
_openErrorLogCommand.Enabled = false;
_openErrorLogCommand.Text = "Solution is initializing";
}
else if (logWatcherSettings.LogWatcherEnabled &&
((logFileStatus?.HasContent ?? false) ||
!_hasSeenErrorLogUpdate))
((logFileStatus?.HasContent ?? false) || !_hasSeenErrorLogUpdate))
{
_openErrorLogCommand.Enabled = true;
_openErrorLogCommand.Text = "Open Orchard error log";
Expand All @@ -176,7 +184,6 @@ private void UpdateOpenErrorLogCommandAccessibilityAndText(ILogFileStatus logFil
_openErrorLogCommand.Text = "Orchard error log doesn't exist or hasn't been updated";
if (!_errorIndicatorStateChanged) _blinkStickManager.TurnOff();
_errorIndicatorStateChanged = true;

}
}

Expand Down
2 changes: 1 addition & 1 deletion Lombiq.Vsix.Orchard/Constants/ExtensionVersion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
{
internal static class ExtensionVersion
{
public const string Current = "1.5.1";
public const string Current = "1.5.2";
}
}
16 changes: 10 additions & 6 deletions Lombiq.Vsix.Orchard/Extensions/AsyncPackageExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Threading.Tasks;

namespace Microsoft.VisualStudio.Shell
{
public static class AsyncPackageExtensions
{
public static void AddService<T>(this AsyncPackage package, Func<System.Threading.Tasks.Task<object>> resolver) =>
public static void AddService<T>(this AsyncPackage package, Func<Task<object>> resolver) =>
package.AddService(typeof(T), (container, cancellationToken, serviceType) => resolver());

public static void AddService<TService, TImplementation>(this AsyncPackage package) where TImplementation : new() =>
Expand All @@ -16,13 +17,16 @@ public static void AddService<T>(this AsyncPackage package, Func<System.Threadin
public static void AddService<T>(this AsyncPackage package, T instance) =>
((IServiceContainer)package).AddService(typeof(T), instance);

public static async System.Threading.Tasks.Task<T> GetServiceAsync<T>(this AsyncPackage package) =>
/// <summary>
/// Gets the DTE object describing the VS IDE instance. Can be called from a background thread too. Don't cache
/// it across scopes!
/// </summary>
public static Task<DTE> GetDteAsync(this AsyncPackage package) => package.GetServiceAsync<DTE>();

public static async Task<T> GetServiceAsync<T>(this AsyncPackage package) =>
(T)(await package.GetServiceAsync(typeof(T)));

public static async System.Threading.Tasks.Task<IEnumerable<T>> GetServicesAsync<T>(this AsyncPackage package) =>
public static async Task<IEnumerable<T>> GetServicesAsync<T>(this AsyncPackage package) =>
(IEnumerable<T>)(await package.GetServiceAsync(typeof(T)));

public static DTE GetDte(this AsyncPackage package) =>
Package.GetGlobalService(typeof(Microsoft.VisualStudio.Shell.Interop.SDTE)) as DTE;
}
}
7 changes: 7 additions & 0 deletions Lombiq.Vsix.Orchard/Extensions/DTEExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace EnvDTE
{
public static class DTEExtensions
{
public static bool SolutionIsOpen(this DTE dte) => dte.Solution.IsOpen;
}
}
1 change: 1 addition & 0 deletions Lombiq.Vsix.Orchard/Lombiq.Vsix.Orchard.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@
<Compile Include="Constants\ExtensionVersion.cs" />
<Compile Include="Exceptions\DependencyToConstructorInjectorException.cs" />
<Compile Include="Extensions\AsyncPackageExtensions.cs" />
<Compile Include="Extensions\DTEExtensions.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Forms\InjectDependencyDialog.cs">
<SubType>Form</SubType>
Expand Down
Loading

0 comments on commit ecf043d

Please sign in to comment.