diff --git a/AxialSqlTools/AxialSqlTools.csproj b/AxialSqlTools/AxialSqlTools.csproj
index b567e7b..0ca717a 100644
--- a/AxialSqlTools/AxialSqlTools.csproj
+++ b/AxialSqlTools/AxialSqlTools.csproj
@@ -143,6 +143,7 @@
+
@@ -404,6 +405,10 @@
MSBuild:Compile
Designer
+
+ MSBuild:Compile
+ Designer
+
diff --git a/AxialSqlTools/DataTransfer/DataTransferWindowControl.xaml b/AxialSqlTools/DataTransfer/DataTransferWindowControl.xaml
index 0ba5480..b91b57f 100644
--- a/AxialSqlTools/DataTransfer/DataTransferWindowControl.xaml
+++ b/AxialSqlTools/DataTransfer/DataTransferWindowControl.xaml
@@ -4,19 +4,37 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vsshell="clr-namespace:Microsoft.VisualStudio.Shell;assembly=Microsoft.VisualStudio.Shell.15.0"
- mc:Ignorable="d" FontSize="14"
- Name="MyToolWindow">
-
+ mc:Ignorable="d"
+ Name="MyToolWindow"
+ Background="{DynamicResource AxialThemeBackgroundBrush}"
+ Foreground="{DynamicResource AxialThemeForegroundBrush}">
+
+
+
+
+
+
+
+
+
-
- Data Transfer
+
+
+ Data Transfer
+
+
+
+
+
+
+
-
-
-
+
@@ -27,11 +45,11 @@
-
+
-
+
@@ -73,8 +91,8 @@
-
-
+
+
@@ -87,7 +105,7 @@
-
+
@@ -143,8 +161,8 @@
-
-
+
+
@@ -158,7 +176,7 @@
-
+
@@ -214,8 +232,8 @@
-
-
+
+
@@ -260,7 +278,7 @@
-
+
@@ -285,8 +303,8 @@
-
-
+
+
@@ -331,7 +349,7 @@
-
+
@@ -356,8 +374,8 @@
-
-
+
+
@@ -375,3 +393,4 @@
+
diff --git a/AxialSqlTools/DataTransfer/DataTransferWindowControl.xaml.cs b/AxialSqlTools/DataTransfer/DataTransferWindowControl.xaml.cs
index 11b8f65..672a588 100644
--- a/AxialSqlTools/DataTransfer/DataTransferWindowControl.xaml.cs
+++ b/AxialSqlTools/DataTransfer/DataTransferWindowControl.xaml.cs
@@ -17,6 +17,8 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
+ using System.Windows.Media;
+ using System.Windows.Navigation;
///
/// Interaction logic for DataTransferWindowControl.
@@ -26,6 +28,7 @@ public partial class DataTransferWindowControl : UserControl
private CancellationTokenSource _cancellationTokenSource;
private Stopwatch stopwatch;
+ private readonly ToolWindowThemeController _themeController;
private string sourceConnectionString = "";
private string targetConnectionString = "";
@@ -69,6 +72,7 @@ public static int GetRowsCopied(SqlBulkCopy bulkCopy)
public DataTransferWindowControl()
{
this.InitializeComponent();
+ _themeController = new ToolWindowThemeController(this, ApplyThemeBrushResources);
Button_CopyData.IsEnabled = false;
ButtonToPsql_CopyData.IsEnabled = false;
@@ -109,6 +113,16 @@ public DataTransferWindowControl()
}
+ private void ApplyThemeBrushResources()
+ {
+ ToolWindowThemeResources.ApplySharedTheme(this);
+ }
+
+ private void WikiLink_RequestNavigate(object sender, RequestNavigateEventArgs e)
+ {
+ ToolWindowNavigation.HandleRequestNavigate(e);
+ }
+
private void Button_EditSavedConnections_Click(object sender, RoutedEventArgs e)
{
var window = new SavedConnectionManagerWindow
diff --git a/AxialSqlTools/HealthDashboards/HealthDashboard_ServerControl.xaml b/AxialSqlTools/HealthDashboards/HealthDashboard_ServerControl.xaml
index ae8dc60..608ef18 100644
--- a/AxialSqlTools/HealthDashboards/HealthDashboard_ServerControl.xaml
+++ b/AxialSqlTools/HealthDashboards/HealthDashboard_ServerControl.xaml
@@ -3,13 +3,22 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:vsshell="clr-namespace:Microsoft.VisualStudio.Shell;assembly=Microsoft.VisualStudio.Shell.15.0"
xmlns:oxy="http://oxyplot.org/wpf"
mc:Ignorable="d"
d:DesignHeight="500" d:DesignWidth="1000"
- x:Name="MyToolWindow">
+ x:Name="MyToolWindow"
+ Background="{DynamicResource AxialThemeBackgroundBrush}"
+ Foreground="{DynamicResource AxialThemeForegroundBrush}">
-
+
+
+
+
+
+
+
+
+
@@ -17,11 +26,19 @@
-
+
Server Health Dashboard
+
+
+
+
+
+
+
public partial class HealthDashboard_ServerControl : UserControl
{
+ private readonly ToolWindowThemeController _themeController;
+ private Brush _statusDefaultBrush;
+ private Brush _statusErrorBrush;
+ private Brush _statusSuccessBrush;
+ private OxyColor _plotTextColor;
+ private OxyColor _plotBackgroundColor;
+ private OxyColor _plotBorderColor;
+ private OxyColor _plotGridlineColor;
+ private OxyColor _plotAccentColor;
+ private OxyColor _plotSuccessColor;
+ private OxyColor _plotErrorColor;
+ private OxyColor _plotNeutralColor;
+ private OxyColor _plotSecondaryColor;
public class WaitsStatsAggregator
{
@@ -179,6 +193,7 @@ public void Dispose()
public HealthDashboard_ServerControl()
{
this.InitializeComponent();
+ _themeController = new ToolWindowThemeController(this, ApplyThemeBrushResources);
BackupTimelinePeriodNumberTextBox.Text = "1";
AgentJobsTimelinePeriodNumberTextBox.Text = "1";
@@ -191,6 +206,25 @@ public HealthDashboard_ServerControl()
}
+ private void ApplyThemeBrushResources()
+ {
+ ToolWindowThemeResources.ApplySharedTheme(this);
+
+ _statusDefaultBrush = GetThemeBrush("AxialThemeForegroundBrush", SystemColors.WindowTextBrush);
+ _statusErrorBrush = GetThemeBrush("AxialThemeStatusErrorBrush", Brushes.Red);
+ _statusSuccessBrush = GetThemeBrush("AxialThemeStatusSuccessBrush", Brushes.Green);
+
+ _plotTextColor = ToOxyColor(VsThemeBrushResolver.GetBrushColor(_statusDefaultBrush, System.Windows.Media.Colors.Black));
+ _plotBackgroundColor = ToOxyColor(VsThemeBrushResolver.GetBrushColor(GetThemeBrush("AxialThemeBackgroundBrush", SystemColors.WindowBrush), System.Windows.Media.Colors.White));
+ _plotBorderColor = ToOxyColor(VsThemeBrushResolver.GetBrushColor(GetThemeBrush("AxialThemeBorderBrush", SystemColors.ActiveBorderBrush), System.Windows.Media.Colors.Gray));
+ _plotGridlineColor = ToOxyColor(VsThemeBrushResolver.GetBrushColor(GetThemeBrush("AxialThemeSubtleBorderBrush", SystemColors.InactiveBorderBrush), System.Windows.Media.Colors.DarkGray));
+ _plotAccentColor = ToOxyColor(VsThemeBrushResolver.GetBrushColor(GetThemeBrush("AxialThemeAccentBrush", Brushes.SteelBlue), System.Windows.Media.Colors.SteelBlue));
+ _plotSuccessColor = ToOxyColor(VsThemeBrushResolver.GetBrushColor(_statusSuccessBrush, System.Windows.Media.Color.FromRgb(0x10, 0x7C, 0x10)));
+ _plotErrorColor = ToOxyColor(VsThemeBrushResolver.GetBrushColor(_statusErrorBrush, System.Windows.Media.Color.FromRgb(0xA1, 0x26, 0x0D)));
+ _plotNeutralColor = ToOxyColor(VsThemeBrushResolver.GetBrushColor(GetThemeBrush("AxialThemeDiffModifiedBackgroundBrush", Brushes.Gray), System.Windows.Media.Color.FromRgb(0x80, 0x80, 0x80)));
+ _plotSecondaryColor = ToOxyColor(VsThemeBrushResolver.GetBrushColor(GetThemeBrush("AxialThemeLinkBrush", Brushes.DodgerBlue), System.Windows.Media.Colors.DodgerBlue));
+ }
+
public void StartMonitoring()
{
if (_monitoringStarted) return;
@@ -254,7 +288,7 @@ public void UpdateUI(int i, HealthDashboardServerMetric metrics, bool doEmpty)
if (metrics.HasException)
{
LabelInternalException.Content = metrics.ExecutionException;
- LabelInternalException.Foreground = Brushes.Red;
+ LabelInternalException.Foreground = _statusErrorBrush;
LabelInternalException.FontWeight = System.Windows.FontWeights.Bold;
return;
@@ -312,30 +346,30 @@ public void UpdateUI(int i, HealthDashboardServerMetric metrics, bool doEmpty)
if (metrics.BlockedRequestsCount > 0)
{
- Label_BlockedRequestCount.Foreground = Brushes.Red;
+ Label_BlockedRequestCount.Foreground = _statusErrorBrush;
Label_BlockedRequestCount.Content = metrics.BlockedRequestsCount.ToString();
ServerHasIssues = true;
}
else {
- Label_BlockedRequestCount.Foreground = Brushes.Black;
+ Label_BlockedRequestCount.Foreground = _statusDefaultBrush;
Label_BlockedRequestCount.Content = "-";
}
if (metrics.BlockingTotalWaitTime > 0)
{
- Label_BlockedTotalWaitTime.Foreground = Brushes.Red;
+ Label_BlockedTotalWaitTime.Foreground = _statusErrorBrush;
Label_BlockedTotalWaitTime.Content = metrics.BlockingTotalWaitTime.ToString();
}
else
{
- Label_BlockedTotalWaitTime.Foreground = Brushes.Black;
+ Label_BlockedTotalWaitTime.Foreground = _statusDefaultBrush;
Label_BlockedTotalWaitTime.Content = "-";
}
//-------------------------------------------------
- Label_DatabaseStatus.Foreground = Brushes.Black;
+ Label_DatabaseStatus.Foreground = _statusDefaultBrush;
if (metrics.CountUserDatabasesTotal == 0)
Label_DatabaseStatus.Content = "no user databases";
else if (metrics.CountUserDatabasesTotal == metrics.CountUserDatabasesOkay)
@@ -343,7 +377,7 @@ public void UpdateUI(int i, HealthDashboardServerMetric metrics, bool doEmpty)
Label_DatabaseStatus.Content = $"OK - {metrics.CountUserDatabasesTotal} database(s)";
} else
{
- Label_DatabaseStatus.Foreground = Brushes.Red;
+ Label_DatabaseStatus.Foreground = _statusErrorBrush;
Label_DatabaseStatus.Content = $"{metrics.CountUserDatabasesOkay} out of {metrics.CountUserDatabasesTotal} available";
ServerHasIssues = true;
}
@@ -360,10 +394,10 @@ public void UpdateUI(int i, HealthDashboardServerMetric metrics, bool doEmpty)
string agStatus = "HEALTHY";
if (metrics.AlwaysOn_Health == 2)
{
- Label_AlwaysOnHealth.Foreground = Brushes.Black;
+ Label_AlwaysOnHealth.Foreground = _statusSuccessBrush;
} else
{
- Label_AlwaysOnHealth.Foreground = Brushes.Red;
+ Label_AlwaysOnHealth.Foreground = _statusErrorBrush;
if (metrics.AlwaysOn_Health == 1)
agStatus = "PARTIALLY HEALTHY";
else agStatus = "NOT HEALTHY";
@@ -417,24 +451,24 @@ public void UpdateUI(int i, HealthDashboardServerMetric metrics, bool doEmpty)
{
LabelPlacement = LabelPlacement.Inside,
LabelFormatString = "{0:0} Gb", // Adjust this to change how the labels are formatted
- StrokeColor = OxyColors.Black,
+ StrokeColor = _plotBorderColor,
StrokeThickness = 1,
IsStacked = true
};
foreach (var disk in metrics.DisksInfo)
- barSeries1.Items.Add(new BarItem { Value = disk.UsedSpaceGb, Color = OxyColors.LightPink });
+ barSeries1.Items.Add(new BarItem { Value = disk.UsedSpaceGb, Color = _plotErrorColor });
barModel.Series.Add(barSeries1);
var barSeries2 = new BarSeries
{
LabelPlacement = LabelPlacement.Inside,
LabelFormatString = "{0:0} Gb", // Adjust this to change how the labels are formatted
- StrokeColor = OxyColors.Black,
+ StrokeColor = _plotBorderColor,
StrokeThickness = 1,
IsStacked = true
};
foreach (var disk in metrics.DisksInfo)
- barSeries2.Items.Add(new BarItem { Value = disk.FreeSpaceGb, Color = OxyColors.LightBlue });
+ barSeries2.Items.Add(new BarItem { Value = disk.FreeSpaceGb, Color = _plotSuccessColor });
barModel.Series.Add(barSeries2);
@@ -458,6 +492,8 @@ public void UpdateUI(int i, HealthDashboardServerMetric metrics, bool doEmpty)
IsPanEnabled = false
});
+ ApplyPlotTheme(barModel);
+
this.DiskInfoModel.Model = barModel;
@@ -583,8 +619,9 @@ private void UpdateWaitStatsGraph(List previousWaitStats, Dictionary<
LegendPosition = LegendPosition.RightTop,
LegendPlacement = LegendPlacement.Outside,
LegendOrientation = LegendOrientation.Vertical,
- LegendBackground = OxyColor.FromAColor(200, OxyColors.White),
- LegendBorder = OxyColors.Black
+ LegendBackground = OxyColor.FromAColor(220, _plotBackgroundColor),
+ LegendBorder = _plotBorderColor,
+ TextColor = _plotTextColor
};
LegendWS.LegendMaxWidth = 200;
@@ -598,7 +635,7 @@ private void UpdateWaitStatsGraph(List previousWaitStats, Dictionary<
{
//LabelPlacement = LabelPlacement.Inside,
//LabelFormatString = "{0:0}", // Adjust this to change how the labels are formatted
- StrokeColor = OxyColors.Black,
+ StrokeColor = _plotBorderColor,
StrokeThickness = 1,
IsStacked = true
};
@@ -614,6 +651,8 @@ private void UpdateWaitStatsGraph(List previousWaitStats, Dictionary<
barModelWS.Series.Add(barSeriesWS);
}
+ ApplyPlotTheme(barModelWS);
+
this.WaitStatsModel.Model = barModelWS;
}
@@ -677,7 +716,9 @@ private PlotModel CreateTimeSeriesModel(string title, string yAxisTitle, Func s.Timestamp))
@@ -686,6 +727,7 @@ private PlotModel CreateTimeSeriesModel(string title, string yAxisTitle, Func
-
+ Name="MyToolWindow"
+ Background="{DynamicResource AxialThemeBackgroundBrush}"
+ Foreground="{DynamicResource AxialThemeForegroundBrush}">
+
+
+
+
+
+
+
+
- HealthDashboard_Servers
+
+ Health Dashboard - Servers
+
+
+
+
+
+
+
+
-
+
diff --git a/AxialSqlTools/HealthDashboards/HealthDashboard_ServersControl.xaml.cs b/AxialSqlTools/HealthDashboards/HealthDashboard_ServersControl.xaml.cs
index d63e853..c0790c6 100644
--- a/AxialSqlTools/HealthDashboards/HealthDashboard_ServersControl.xaml.cs
+++ b/AxialSqlTools/HealthDashboards/HealthDashboard_ServersControl.xaml.cs
@@ -5,12 +5,15 @@
using System.Diagnostics.CodeAnalysis;
using System.Windows;
using System.Windows.Controls;
+ using System.Windows.Navigation;
///
/// Interaction logic for HealthDashboard_ServersControl.
///
public partial class HealthDashboard_ServersControl : UserControl
{
+ private readonly ToolWindowThemeController _themeController;
+
///
/// Initializes a new instance of the class.
///
@@ -21,6 +24,7 @@ public partial class HealthDashboard_ServersControl : UserControl
public HealthDashboard_ServersControl()
{
this.InitializeComponent();
+ _themeController = new ToolWindowThemeController(this, ApplyThemeBrushResources);
Items = new ObservableCollection();
// Bind the collection to the DataGrid
@@ -34,6 +38,16 @@ public HealthDashboard_ServersControl()
}
+ private void ApplyThemeBrushResources()
+ {
+ ToolWindowThemeResources.ApplySharedTheme(this);
+ }
+
+ private void WikiLink_RequestNavigate(object sender, RequestNavigateEventArgs e)
+ {
+ ToolWindowNavigation.HandleRequestNavigate(e);
+ }
+
///
/// Handles click on the button by displaying a message box.
///
diff --git a/AxialSqlTools/Modules/ToolWindowThemeSupport.cs b/AxialSqlTools/Modules/ToolWindowThemeSupport.cs
new file mode 100644
index 0000000..6877dfc
--- /dev/null
+++ b/AxialSqlTools/Modules/ToolWindowThemeSupport.cs
@@ -0,0 +1,315 @@
+namespace AxialSqlTools
+{
+ using System;
+ using System.Diagnostics;
+ using System.Reflection;
+ using System.Windows;
+ using System.Windows.Media;
+ using System.Windows.Navigation;
+ using Microsoft.VisualStudio.PlatformUI;
+ using Microsoft.VisualStudio.Shell;
+
+ internal static class VsThemeBrushResolver
+ {
+ public static Brush ResolveBrush(FrameworkElement scope, object resourceKey)
+ {
+ if (resourceKey == null)
+ {
+ return null;
+ }
+
+ return scope?.TryFindResource(resourceKey) as Brush
+ ?? Application.Current?.TryFindResource(resourceKey) as Brush;
+ }
+
+ public static Brush ResolveEnvironmentBrushByName(FrameworkElement scope, string keyName)
+ {
+ if (string.IsNullOrWhiteSpace(keyName))
+ {
+ return null;
+ }
+
+ PropertyInfo property = typeof(EnvironmentColors).GetProperty(keyName, BindingFlags.Public | BindingFlags.Static);
+ object key = property?.GetValue(null);
+ return ResolveBrush(scope, key);
+ }
+
+ public static Color GetBrushColor(Brush brush, Color fallback)
+ {
+ if (brush is SolidColorBrush solidBrush)
+ {
+ return solidBrush.Color;
+ }
+
+ return fallback;
+ }
+
+ public static double GetRelativeLuminance(Color color)
+ {
+ double r = color.R / 255.0;
+ double g = color.G / 255.0;
+ double b = color.B / 255.0;
+
+ double rLinear = r <= 0.03928 ? r / 12.92 : Math.Pow((r + 0.055) / 1.055, 2.4);
+ double gLinear = g <= 0.03928 ? g / 12.92 : Math.Pow((g + 0.055) / 1.055, 2.4);
+ double bLinear = b <= 0.03928 ? b / 12.92 : Math.Pow((b + 0.055) / 1.055, 2.4);
+
+ return 0.2126 * rLinear + 0.7152 * gLinear + 0.0722 * bLinear;
+ }
+
+ public static Color BlendColors(Color baseColor, Color blendColor, double blendAmount)
+ {
+ blendAmount = Math.Max(0.0, Math.Min(1.0, blendAmount));
+ byte r = (byte)Math.Round((baseColor.R * (1.0 - blendAmount)) + (blendColor.R * blendAmount));
+ byte g = (byte)Math.Round((baseColor.G * (1.0 - blendAmount)) + (blendColor.G * blendAmount));
+ byte b = (byte)Math.Round((baseColor.B * (1.0 - blendAmount)) + (blendColor.B * blendAmount));
+ return Color.FromRgb(r, g, b);
+ }
+ }
+
+ internal static class ToolWindowThemeResources
+ {
+ public static void ApplySharedTheme(FrameworkElement control)
+ {
+ Brush bg = VsThemeBrushResolver.ResolveBrush(control, EnvironmentColors.ToolWindowBackgroundBrushKey)
+ ?? SystemColors.WindowBrush;
+ Brush fg = VsThemeBrushResolver.ResolveBrush(control, EnvironmentColors.ToolWindowTextBrushKey)
+ ?? SystemColors.WindowTextBrush;
+ Brush border = VsThemeBrushResolver.ResolveBrush(control, EnvironmentColors.ToolWindowBorderBrushKey)
+ ?? SystemColors.ActiveBorderBrush;
+ Brush link = VsThemeBrushResolver.ResolveBrush(control, EnvironmentColors.ControlLinkTextBrushKey)
+ ?? SystemColors.HotTrackBrush;
+ Brush accent = VsThemeBrushResolver.ResolveEnvironmentBrushByName(control, "MainWindowActiveDefaultBorderBrushKey")
+ ?? VsThemeBrushResolver.ResolveEnvironmentBrushByName(control, "SystemAccentBrushKey")
+ ?? border;
+ Brush success = VsThemeBrushResolver.ResolveEnvironmentBrushByName(control, "SystemGreenTextBrushKey")
+ ?? new SolidColorBrush(Color.FromRgb(0x10, 0x7C, 0x10));
+ Brush error = VsThemeBrushResolver.ResolveEnvironmentBrushByName(control, "SystemRedTextBrushKey")
+ ?? new SolidColorBrush(Color.FromRgb(0xA1, 0x26, 0x0D));
+
+ Color bgColor = VsThemeBrushResolver.GetBrushColor(bg, Colors.White);
+ Color fgColor = VsThemeBrushResolver.GetBrushColor(fg, Colors.Black);
+ Color accentColor = VsThemeBrushResolver.GetBrushColor(accent, Color.FromRgb(0x00, 0x7A, 0xCC));
+ Color successColor = VsThemeBrushResolver.GetBrushColor(success, Color.FromRgb(0x10, 0x7C, 0x10));
+ Color errorColor = VsThemeBrushResolver.GetBrushColor(error, Color.FromRgb(0xA1, 0x26, 0x0D));
+ bool isLightTheme = VsThemeBrushResolver.GetRelativeLuminance(bgColor) > 0.6;
+
+ Color headerColor = isLightTheme
+ ? VsThemeBrushResolver.BlendColors(bgColor, Colors.Black, 0.04)
+ : VsThemeBrushResolver.BlendColors(bgColor, Colors.White, 0.04);
+ Color tabHeaderColor = isLightTheme
+ ? VsThemeBrushResolver.BlendColors(bgColor, Colors.Black, 0.05)
+ : VsThemeBrushResolver.BlendColors(bgColor, Colors.White, 0.06);
+ Color tabHoverColor = isLightTheme
+ ? VsThemeBrushResolver.BlendColors(bgColor, Colors.Black, 0.10)
+ : VsThemeBrushResolver.BlendColors(bgColor, Colors.White, 0.12);
+ Color tabSelectedColor = isLightTheme
+ ? VsThemeBrushResolver.BlendColors(bgColor, Colors.Black, 0.16)
+ : VsThemeBrushResolver.BlendColors(bgColor, Colors.White, 0.18);
+ Color buttonBackgroundColor = isLightTheme
+ ? VsThemeBrushResolver.BlendColors(bgColor, Colors.Black, 0.06)
+ : VsThemeBrushResolver.BlendColors(bgColor, Colors.White, 0.08);
+ Color buttonHoverColor = isLightTheme
+ ? VsThemeBrushResolver.BlendColors(bgColor, Colors.Black, 0.14)
+ : VsThemeBrushResolver.BlendColors(bgColor, Colors.Black, 0.10);
+ Color buttonPressedColor = isLightTheme
+ ? VsThemeBrushResolver.BlendColors(bgColor, Colors.Black, 0.22)
+ : VsThemeBrushResolver.BlendColors(bgColor, Colors.Black, 0.18);
+ Color subtleBorderColor = isLightTheme
+ ? VsThemeBrushResolver.BlendColors(bgColor, Colors.Black, 0.16)
+ : VsThemeBrushResolver.BlendColors(bgColor, Colors.White, 0.14);
+ Color primaryHoverColor = isLightTheme
+ ? VsThemeBrushResolver.BlendColors(accentColor, Colors.White, 0.10)
+ : VsThemeBrushResolver.BlendColors(accentColor, Colors.White, 0.14);
+ Color primaryPressedColor = isLightTheme
+ ? VsThemeBrushResolver.BlendColors(accentColor, Colors.Black, 0.12)
+ : VsThemeBrushResolver.BlendColors(accentColor, Colors.Black, 0.16);
+ Color primaryForegroundColor = VsThemeBrushResolver.GetRelativeLuminance(accentColor) > 0.55
+ ? Colors.Black
+ : Colors.White;
+ Color dangerHoverColor = isLightTheme
+ ? VsThemeBrushResolver.BlendColors(errorColor, Colors.White, 0.08)
+ : VsThemeBrushResolver.BlendColors(errorColor, Colors.White, 0.10);
+ Color dangerPressedColor = isLightTheme
+ ? VsThemeBrushResolver.BlendColors(errorColor, Colors.Black, 0.12)
+ : VsThemeBrushResolver.BlendColors(errorColor, Colors.Black, 0.16);
+ Color dangerForegroundColor = VsThemeBrushResolver.GetRelativeLuminance(errorColor) > 0.55
+ ? Colors.Black
+ : Colors.White;
+ Color gridHeaderColor = isLightTheme
+ ? VsThemeBrushResolver.BlendColors(bgColor, Colors.Black, 0.03)
+ : VsThemeBrushResolver.BlendColors(bgColor, Colors.White, 0.08);
+ Color gridAlternateRowColor = isLightTheme
+ ? VsThemeBrushResolver.BlendColors(bgColor, Colors.Black, 0.02)
+ : VsThemeBrushResolver.BlendColors(bgColor, Colors.White, 0.04);
+ Color gridSelectionColor = isLightTheme
+ ? VsThemeBrushResolver.BlendColors(bgColor, Colors.Black, 0.12)
+ : VsThemeBrushResolver.BlendColors(bgColor, Colors.White, 0.14);
+ Color diffInsertedBackgroundColor = isLightTheme
+ ? VsThemeBrushResolver.BlendColors(bgColor, successColor, 0.20)
+ : VsThemeBrushResolver.BlendColors(bgColor, successColor, 0.36);
+ Color diffDeletedBackgroundColor = isLightTheme
+ ? VsThemeBrushResolver.BlendColors(bgColor, errorColor, 0.20)
+ : VsThemeBrushResolver.BlendColors(bgColor, errorColor, 0.36);
+ Color diffModifiedBackgroundColor = isLightTheme
+ ? VsThemeBrushResolver.BlendColors(bgColor, fgColor, 0.10)
+ : VsThemeBrushResolver.BlendColors(bgColor, fgColor, 0.20);
+ Color diffInsertedForegroundColor = VsThemeBrushResolver.GetRelativeLuminance(diffInsertedBackgroundColor) > 0.52
+ ? Colors.Black
+ : Colors.White;
+ Color diffDeletedForegroundColor = VsThemeBrushResolver.GetRelativeLuminance(diffDeletedBackgroundColor) > 0.52
+ ? Colors.Black
+ : Colors.White;
+ Color diffModifiedForegroundColor = VsThemeBrushResolver.GetRelativeLuminance(diffModifiedBackgroundColor) > 0.52
+ ? Colors.Black
+ : Colors.White;
+
+ control.Resources["AxialThemeBackgroundBrush"] = bg;
+ control.Resources["AxialThemeForegroundBrush"] = fg;
+ control.Resources["AxialThemeBorderBrush"] = border;
+ control.Resources["AxialThemeSubtleBorderBrush"] = new SolidColorBrush(subtleBorderColor);
+ control.Resources["AxialThemeHeaderBackgroundBrush"] = new SolidColorBrush(headerColor);
+ control.Resources["AxialThemeLinkBrush"] = link;
+ control.Resources["AxialThemeAccentBrush"] = new SolidColorBrush(accentColor);
+ control.Resources["AxialThemeStatusErrorBrush"] = error;
+ control.Resources["AxialThemeStatusSuccessBrush"] = success;
+ control.Resources["AxialThemeTabHeaderBackgroundBrush"] = new SolidColorBrush(tabHeaderColor);
+ control.Resources["AxialThemeTabHeaderHoverBrush"] = new SolidColorBrush(tabHoverColor);
+ control.Resources["AxialThemeTabHeaderSelectedBrush"] = new SolidColorBrush(tabSelectedColor);
+ control.Resources["AxialThemeButtonBackgroundBrush"] = new SolidColorBrush(buttonBackgroundColor);
+ control.Resources["AxialThemeButtonHoverBrush"] = new SolidColorBrush(buttonHoverColor);
+ control.Resources["AxialThemeButtonPressedBrush"] = new SolidColorBrush(buttonPressedColor);
+ control.Resources["AxialThemePrimaryButtonBackgroundBrush"] = new SolidColorBrush(accentColor);
+ control.Resources["AxialThemePrimaryButtonHoverBrush"] = new SolidColorBrush(primaryHoverColor);
+ control.Resources["AxialThemePrimaryButtonPressedBrush"] = new SolidColorBrush(primaryPressedColor);
+ control.Resources["AxialThemePrimaryButtonForegroundBrush"] = new SolidColorBrush(primaryForegroundColor);
+ control.Resources["AxialThemeDangerButtonBackgroundBrush"] = new SolidColorBrush(errorColor);
+ control.Resources["AxialThemeDangerButtonHoverBrush"] = new SolidColorBrush(dangerHoverColor);
+ control.Resources["AxialThemeDangerButtonPressedBrush"] = new SolidColorBrush(dangerPressedColor);
+ control.Resources["AxialThemeDangerButtonForegroundBrush"] = new SolidColorBrush(dangerForegroundColor);
+ control.Resources["AxialThemeGridHeaderBackgroundBrush"] = new SolidColorBrush(gridHeaderColor);
+ control.Resources["AxialThemeGridAlternateRowBrush"] = new SolidColorBrush(gridAlternateRowColor);
+ control.Resources["AxialThemeGridSelectionBrush"] = new SolidColorBrush(gridSelectionColor);
+ control.Resources["AxialThemeDiffInsertedBackgroundBrush"] = new SolidColorBrush(diffInsertedBackgroundColor);
+ control.Resources["AxialThemeDiffInsertedForegroundBrush"] = new SolidColorBrush(diffInsertedForegroundColor);
+ control.Resources["AxialThemeDiffDeletedBackgroundBrush"] = new SolidColorBrush(diffDeletedBackgroundColor);
+ control.Resources["AxialThemeDiffDeletedForegroundBrush"] = new SolidColorBrush(diffDeletedForegroundColor);
+ control.Resources["AxialThemeDiffModifiedBackgroundBrush"] = new SolidColorBrush(diffModifiedBackgroundColor);
+ control.Resources["AxialThemeDiffModifiedForegroundBrush"] = new SolidColorBrush(diffModifiedForegroundColor);
+ }
+ }
+
+ internal sealed class ToolWindowThemeController : IDisposable
+ {
+ private readonly FrameworkElement control;
+ private readonly Action applyTheme;
+ private bool isThemeSubscribed;
+
+ public ToolWindowThemeController(FrameworkElement control, Action applyTheme)
+ {
+ this.control = control ?? throw new ArgumentNullException(nameof(control));
+ this.applyTheme = applyTheme ?? throw new ArgumentNullException(nameof(applyTheme));
+
+ this.control.Loaded += OnLoaded;
+ this.control.Unloaded += OnUnloaded;
+ this.control.IsVisibleChanged += OnIsVisibleChanged;
+
+ this.applyTheme();
+ }
+
+ private void OnLoaded(object sender, RoutedEventArgs e)
+ {
+ ThreadHelper.ThrowIfNotOnUIThread();
+
+ applyTheme();
+ SubscribeToThemeChanges();
+ }
+
+ private void OnUnloaded(object sender, RoutedEventArgs e)
+ {
+ UnsubscribeFromThemeChanges();
+ }
+
+ private void OnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
+ {
+ ThreadHelper.ThrowIfNotOnUIThread();
+
+ if (control.IsVisible)
+ {
+ applyTheme();
+ }
+ }
+
+ private void SubscribeToThemeChanges()
+ {
+ if (isThemeSubscribed)
+ {
+ return;
+ }
+
+ VSColorTheme.ThemeChanged += OnVsThemeChanged;
+ isThemeSubscribed = true;
+ }
+
+ private void UnsubscribeFromThemeChanges()
+ {
+ if (!isThemeSubscribed)
+ {
+ return;
+ }
+
+ VSColorTheme.ThemeChanged -= OnVsThemeChanged;
+ isThemeSubscribed = false;
+ }
+
+ private void OnVsThemeChanged(ThemeChangedEventArgs e)
+ {
+ if (!control.Dispatcher.CheckAccess())
+ {
+ control.Dispatcher.BeginInvoke(new Action(applyTheme));
+ return;
+ }
+
+ applyTheme();
+ }
+
+ public void Dispose()
+ {
+ control.Loaded -= OnLoaded;
+ control.Unloaded -= OnUnloaded;
+ control.IsVisibleChanged -= OnIsVisibleChanged;
+ UnsubscribeFromThemeChanges();
+ }
+ }
+
+ internal static class ToolWindowNavigation
+ {
+ public static bool OpenExternalUrl(string url)
+ {
+ if (string.IsNullOrWhiteSpace(url))
+ {
+ return false;
+ }
+
+ Process.Start(new ProcessStartInfo(url)
+ {
+ UseShellExecute = true,
+ });
+
+ return true;
+ }
+
+ public static void HandleRequestNavigate(RequestNavigateEventArgs e)
+ {
+ if (e == null)
+ {
+ return;
+ }
+
+ if (OpenExternalUrl(e.Uri?.AbsoluteUri))
+ {
+ e.Handled = true;
+ }
+ }
+ }
+}
diff --git a/AxialSqlTools/QueryHistory/QueryHistoryWindowCommand.cs b/AxialSqlTools/QueryHistory/QueryHistoryWindowCommand.cs
index cd06d63..2f19552 100644
--- a/AxialSqlTools/QueryHistory/QueryHistoryWindowCommand.cs
+++ b/AxialSqlTools/QueryHistory/QueryHistoryWindowCommand.cs
@@ -90,14 +90,27 @@ private void Execute(object sender, EventArgs e)
{
await Microsoft.VisualStudio.Shell.ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
- ToolWindowPane window = await this.package.ShowToolWindowAsync(typeof(QueryHistoryWindow), 0, true, this.package.DisposalToken);
- if ((null == window) || (null == window.Frame))
+ try
{
- throw new NotSupportedException("Cannot create tool window");
- }
+ ToolWindowPane window = await this.package.ShowToolWindowAsync(typeof(QueryHistoryWindow), 0, true, this.package.DisposalToken);
+ if ((null == window) || (null == window.Frame))
+ {
+ throw new NotSupportedException("Cannot create tool window");
+ }
- IVsWindowFrame windowFrame = (IVsWindowFrame)window.Frame;
- windowFrame.SetProperty((int)__VSFPROPID.VSFPROPID_FrameMode, VSFRAMEMODE.VSFM_MdiChild);
+ IVsWindowFrame windowFrame = (IVsWindowFrame)window.Frame;
+ windowFrame.SetProperty((int)__VSFPROPID.VSFPROPID_FrameMode, VSFRAMEMODE.VSFM_MdiChild);
+ }
+ catch (Exception ex)
+ {
+ VsShellUtilities.ShowMessageBox(
+ this.package,
+ "Failed to open Query History. " + ex.Message,
+ "Axial SQL Tools",
+ OLEMSGICON.OLEMSGICON_CRITICAL,
+ OLEMSGBUTTON.OLEMSGBUTTON_OK,
+ OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
+ }
});
}
diff --git a/AxialSqlTools/QueryHistory/QueryHistoryWindowControl.xaml b/AxialSqlTools/QueryHistory/QueryHistoryWindowControl.xaml
index 5b8e13e..e827582 100644
--- a/AxialSqlTools/QueryHistory/QueryHistoryWindowControl.xaml
+++ b/AxialSqlTools/QueryHistory/QueryHistoryWindowControl.xaml
@@ -7,9 +7,39 @@
mc:Ignorable="d"
d:DesignHeight="800"
d:DesignWidth="1000"
- Name="MyToolWindow">
+ Name="MyToolWindow"
+ Background="{DynamicResource AxialThemeBackgroundBrush}"
+ Foreground="{DynamicResource AxialThemeForegroundBrush}">
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
@@ -57,7 +87,7 @@
-
@@ -70,11 +100,12 @@
@@ -101,7 +132,11 @@
ItemsSource="{Binding QueryHistoryRecords}"
SelectedItem="{Binding SelectedRecord, Mode=TwoWay}"
AutoGenerateColumns="False"
- SelectionMode="Single">
+ SelectionMode="Single"
+ Style="{DynamicResource AxialThemedDataGridStyle}"
+ ColumnHeaderStyle="{DynamicResource AxialThemedDataGridColumnHeaderStyle}"
+ CellStyle="{DynamicResource AxialThemedDataGridCellStyle}"
+ RowStyle="{DynamicResource AxialThemedDataGridRowStyle}">
@@ -115,7 +142,7 @@
-
@@ -123,7 +150,7 @@
-
@@ -182,7 +215,7 @@
-
@@ -190,7 +223,7 @@
-
-
-
diff --git a/AxialSqlTools/SqlServerBuilds/SqlServerBuildsWindowControl.xaml.cs b/AxialSqlTools/SqlServerBuilds/SqlServerBuildsWindowControl.xaml.cs
index 3bd81b1..f3ba0f9 100644
--- a/AxialSqlTools/SqlServerBuilds/SqlServerBuildsWindowControl.xaml.cs
+++ b/AxialSqlTools/SqlServerBuilds/SqlServerBuildsWindowControl.xaml.cs
@@ -2,7 +2,6 @@
using Microsoft.VisualStudio.Shell.Interop;
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Text;
using System.Windows;
using System.Windows.Controls;
@@ -17,9 +16,18 @@ namespace AxialSqlTools
///
public partial class SqlServerBuildsWindowControl : UserControl
{
+ private readonly ToolWindowThemeController _themeController;
+
public SqlServerBuildsWindowControl()
{
this.InitializeComponent();
+ _themeController = new ToolWindowThemeController(this, ApplyThemeBrushResources);
+ LoadSqlVersions();
+ }
+
+ private void ApplyThemeBrushResources()
+ {
+ ToolWindowThemeResources.ApplySharedTheme(this);
LoadSqlVersions();
}
@@ -28,6 +36,11 @@ private void LoadSqlVersions()
var sqlVersions = AxialSqlToolsPackage.PackageInstance.SQLBuildsDataInfo;
sqlVersionTreeView.Items.Clear(); // Clear previous items
+ Brush groupHeaderBrush = ResolveThemeBrush("AxialThemeAccentBrush", Brushes.DarkBlue);
+ Brush headerBackgroundBrush = ResolveThemeBrush("AxialThemeGridHeaderBackgroundBrush", Brushes.LightGray);
+ Brush foregroundBrush = ResolveThemeBrush("AxialThemeForegroundBrush", Brushes.Black);
+ Brush linkBrush = ResolveThemeBrush("AxialThemeLinkBrush", Brushes.Blue);
+
// Add Group Headers
foreach (var majorVersion in sqlVersions.Builds)
{
@@ -35,17 +48,17 @@ private void LoadSqlVersions()
{
Header = $"SQL Server {majorVersion.Key}",
FontWeight = FontWeights.Bold,
- Foreground = Brushes.DarkBlue,
+ Foreground = groupHeaderBrush,
IsExpanded = true
};
// Add Column Headers (Styled like a ListView)
- StackPanel headerPanel = new StackPanel { Orientation = Orientation.Horizontal, Background = Brushes.LightGray };
- headerPanel.Children.Add(CreateColumnText("Build Number", 120, FontWeights.Bold));
- headerPanel.Children.Add(CreateColumnText("KB Number", 120, FontWeights.Bold));
- headerPanel.Children.Add(CreateColumnText("Release Date", 120, FontWeights.Bold));
- headerPanel.Children.Add(CreateColumnText("Update Name", 100, FontWeights.Bold));
- headerPanel.Children.Add(CreateColumnText("URL", 150, FontWeights.Bold));
+ StackPanel headerPanel = new StackPanel { Orientation = Orientation.Horizontal, Background = headerBackgroundBrush };
+ headerPanel.Children.Add(CreateColumnText("Build Number", 120, foregroundBrush, FontWeights.Bold));
+ headerPanel.Children.Add(CreateColumnText("KB Number", 120, foregroundBrush, FontWeights.Bold));
+ headerPanel.Children.Add(CreateColumnText("Release Date", 120, foregroundBrush, FontWeights.Bold));
+ headerPanel.Children.Add(CreateColumnText("Update Name", 100, foregroundBrush, FontWeights.Bold));
+ headerPanel.Children.Add(CreateColumnText("URL", 150, foregroundBrush, FontWeights.Bold));
groupNode.Items.Add(new TreeViewItem { Header = headerPanel, IsEnabled = false });
@@ -56,17 +69,17 @@ private void LoadSqlVersions()
if (update.BuildNumber != null)
{
- rowPanel.Children.Add(CreateColumnText(update.BuildNumber.ToString(), 120));
+ rowPanel.Children.Add(CreateColumnText(update.BuildNumber.ToString(), 120, foregroundBrush));
}
else
{
- rowPanel.Children.Add(CreateColumnText("n/a", 120));
+ rowPanel.Children.Add(CreateColumnText("n/a", 120, foregroundBrush));
}
- rowPanel.Children.Add(CreateColumnText(update.KbNumber, 100));
- rowPanel.Children.Add(CreateColumnText(update.ReleaseDate.ToString("yyyy-MM-dd"), 120));
- rowPanel.Children.Add(CreateColumnText(update.UpdateName, 100));
+ rowPanel.Children.Add(CreateColumnText(update.KbNumber, 100, foregroundBrush));
+ rowPanel.Children.Add(CreateColumnText(update.ReleaseDate.ToString("yyyy-MM-dd"), 120, foregroundBrush));
+ rowPanel.Children.Add(CreateColumnText(update.UpdateName, 100, foregroundBrush));
- TextBlock link = CreateHyperlink(update.Url, 150);
+ TextBlock link = CreateHyperlink(update.Url, 150, linkBrush);
rowPanel.Children.Add(link);
TreeViewItem updateNode = new TreeViewItem { Header = rowPanel };
@@ -78,26 +91,27 @@ private void LoadSqlVersions()
}
// Helper to create text column
- private TextBlock CreateColumnText(string text, double width, FontWeight fontWeight = default)
+ private TextBlock CreateColumnText(string text, double width, Brush foregroundBrush, FontWeight fontWeight = default)
{
return new TextBlock
{
Text = text,
Width = width,
+ Foreground = foregroundBrush,
FontWeight = fontWeight,
Margin = new Thickness(5, 2, 5, 2)
};
}
// Helper to create hyperlink column
- private TextBlock CreateHyperlink(string url, double width)
+ private TextBlock CreateHyperlink(string url, double width, Brush foregroundBrush)
{
string normalizedUrl = NormalizeUrl(url);
TextBlock link = new TextBlock
{
Text = "More Info",
Width = width,
- Foreground = Brushes.Blue,
+ Foreground = foregroundBrush,
TextDecorations = TextDecorations.Underline,
Cursor = System.Windows.Input.Cursors.Hand
};
@@ -155,12 +169,20 @@ private static string NormalizeUrl(string url)
return url.StartsWith("HYPERLINK(") ? ExtractUrlAfter_HYPERLINK(url) : url;
}
+ private Brush ResolveThemeBrush(string resourceKey, Brush fallback)
+ {
+ return TryFindResource(resourceKey) as Brush ?? fallback;
+ }
+
private void OpenUrl(string url)
{
try
{
url = NormalizeUrl(url);
- Process.Start(new ProcessStartInfo(url) { UseShellExecute = true });
+ if (!ToolWindowNavigation.OpenExternalUrl(url))
+ {
+ throw new InvalidOperationException("URL is empty.");
+ }
} catch (Exception ex)
{
@@ -176,7 +198,7 @@ private void OpenUrl(string url)
private void HyperlinkDataSource_Click(object sender, RoutedEventArgs e)
{
- Process.Start(new ProcessStartInfo("https://aka.ms/sqlserverbuilds") { UseShellExecute = true });
+ OpenUrl("https://aka.ms/sqlserverbuilds");
}
///
diff --git a/AxialSqlTools/SyncToGitHub/DatabaseScripterToolWindowControl.xaml b/AxialSqlTools/SyncToGitHub/DatabaseScripterToolWindowControl.xaml
index ed53ff8..71e020f 100644
--- a/AxialSqlTools/SyncToGitHub/DatabaseScripterToolWindowControl.xaml
+++ b/AxialSqlTools/SyncToGitHub/DatabaseScripterToolWindowControl.xaml
@@ -5,12 +5,21 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignWidth="600"
- Name="MyToolWindow">
-
+ Name="MyToolWindow"
+ Background="{DynamicResource AxialThemeBackgroundBrush}"
+ Foreground="{DynamicResource AxialThemeForegroundBrush}">
+
+
+
+
+
+
+
+
-
+
Sync to GitHub
@@ -30,7 +39,7 @@
-
+
@@ -48,7 +57,7 @@
-
+
@@ -65,19 +74,19 @@
+ Opacity="0.72"/>
+ Opacity="0.72"/>
-
+
@@ -85,6 +94,9 @@
@@ -106,29 +121,44 @@
-
+
-
+
-
+
-
+
-
+
-
+
@@ -144,7 +174,10 @@
-
+
@@ -157,7 +190,7 @@
+ Style="{DynamicResource AxialDangerButtonStyle}"/>
diff --git a/AxialSqlTools/SyncToGitHub/DatabaseScripterToolWindowControl.xaml.cs b/AxialSqlTools/SyncToGitHub/DatabaseScripterToolWindowControl.xaml.cs
index 79fb9d3..291c994 100644
--- a/AxialSqlTools/SyncToGitHub/DatabaseScripterToolWindowControl.xaml.cs
+++ b/AxialSqlTools/SyncToGitHub/DatabaseScripterToolWindowControl.xaml.cs
@@ -8,7 +8,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
-using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
@@ -26,6 +25,8 @@ namespace AxialSqlTools
{
public partial class DatabaseScripterToolWindowControl : UserControl
{
+ private readonly ToolWindowThemeController _themeController;
+
// ripped out of Ola script using AI - https://github.com/olahallengren/sql-server-maintenance-solution/
private string _dbPullQuery = @"
SET NOCOUNT ON;
@@ -179,8 +180,7 @@ public SmoObjectMap(
private void buttonWikiPage_Click(object sender, RequestNavigateEventArgs e)
{
- Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) { UseShellExecute = true });
- e.Handled = true;
+ ToolWindowNavigation.HandleRequestNavigate(e);
}
@@ -226,11 +226,7 @@ private void UpdateRepoInfo(GitHubSyncProfile profile)
private void RepoUrlHyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
{
- if (e.Uri != null)
- {
- Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) { UseShellExecute = true });
- }
- e.Handled = true;
+ ToolWindowNavigation.HandleRequestNavigate(e);
}
@@ -421,6 +417,7 @@ private void ProfilesComboBox_SelectionChanged(object sender, SelectionChangedEv
public DatabaseScripterToolWindowControl()
{
InitializeComponent();
+ _themeController = new ToolWindowThemeController(this, ApplyThemeBrushResources);
ProgressListBox.ItemsSource = _progressMessages;
_profiles = new ObservableCollection(ProfileStore.Load());
@@ -429,6 +426,11 @@ public DatabaseScripterToolWindowControl()
UpdateMainFrameState();
}
+ private void ApplyThemeBrushResources()
+ {
+ ToolWindowThemeResources.ApplySharedTheme(this);
+ }
+
private async void RunButton_Click(object sender, RoutedEventArgs e)
{
diff --git a/AxialSqlTools/Themes/SharedToolWindowTheme.xaml b/AxialSqlTools/Themes/SharedToolWindowTheme.xaml
new file mode 100644
index 0000000..d54fc0e
--- /dev/null
+++ b/AxialSqlTools/Themes/SharedToolWindowTheme.xaml
@@ -0,0 +1,510 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AxialSqlTools/WindowSettings/SettingsWindowControl.xaml b/AxialSqlTools/WindowSettings/SettingsWindowControl.xaml
index 6d60236..8b909ee 100644
--- a/AxialSqlTools/WindowSettings/SettingsWindowControl.xaml
+++ b/AxialSqlTools/WindowSettings/SettingsWindowControl.xaml
@@ -4,20 +4,31 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
- Name="MyToolWindow">
+ Name="MyToolWindow"
+ Background="{DynamicResource AxialThemeBackgroundBrush}"
+ Foreground="{DynamicResource AxialThemeForegroundBrush}">
+
+
+
+
+
+
+
+
-
+
+ Background="{DynamicResource AxialThemeHeaderBackgroundBrush}"
+ Padding="12" BorderBrush="{DynamicResource AxialThemeBorderBrush}" BorderThickness="0,0,0,1">
+ HorizontalAlignment="Left"/>
@@ -68,11 +79,9 @@
FontWeight="Bold"
HorizontalAlignment="Left">
-
+
+
+
@@ -165,11 +174,9 @@
FontWeight="Bold"
HorizontalAlignment="Left">
-
+
+
+
@@ -275,11 +282,9 @@
Margin="5"
FontWeight="Bold" HorizontalAlignment="Left">
-
+
+
+
@@ -381,11 +386,9 @@
HorizontalAlignment="Left"
FontWeight="Bold">
-
+
+
+
@@ -504,11 +507,9 @@
HorizontalAlignment="Left"
FontWeight="Bold">
-
+
+
+
@@ -567,7 +568,9 @@
@@ -652,11 +655,9 @@
VerticalAlignment="Top"
FontWeight="Bold">
-
+
+
+
@@ -707,11 +708,9 @@
VerticalAlignment="Top"
FontWeight="Bold">
-
+
+
+
diff --git a/AxialSqlTools/WindowSettings/SettingsWindowControl.xaml.cs b/AxialSqlTools/WindowSettings/SettingsWindowControl.xaml.cs
index 89a965e..c1bdec8 100644
--- a/AxialSqlTools/WindowSettings/SettingsWindowControl.xaml.cs
+++ b/AxialSqlTools/WindowSettings/SettingsWindowControl.xaml.cs
@@ -3,7 +3,6 @@
using Microsoft.Data.SqlClient;
using Newtonsoft.Json.Linq;
using System;
- using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.IO.Compression;
@@ -24,6 +23,7 @@ public partial class SettingsWindowControl : UserControl
{
private string _queryHistoryConnectionString;
+ private readonly ToolWindowThemeController _themeController;
private string tsqlFormatExample = @"while (1=0)
begin
@@ -49,6 +49,7 @@ public SettingsWindowControl()
{
this.InitializeComponent();
+ _themeController = new ToolWindowThemeController(this, ApplyThemeBrushResources);
LoadSavedSettings();
this.Loaded += UserControl_Loaded;
@@ -64,6 +65,31 @@ private void UserControl_Loaded(object sender, System.Windows.RoutedEventArgs e)
LoadSavedSettings();
}
+ private void ApplyThemeBrushResources()
+ {
+ ToolWindowThemeResources.ApplySharedTheme(this);
+
+ ApplyGoogleSheetsAuthorizationBrush();
+ }
+
+ private Brush GetThemedStatusBrush(bool isSuccess)
+ {
+ string key = isSuccess ? "AxialThemeStatusSuccessBrush" : "AxialThemeStatusErrorBrush";
+ return Resources[key] as Brush
+ ?? (isSuccess ? new SolidColorBrush(Color.FromRgb(0x10, 0x7C, 0x10)) : new SolidColorBrush(Color.FromRgb(0xA1, 0x26, 0x0D)));
+ }
+
+ private void ApplyGoogleSheetsAuthorizationBrush()
+ {
+ if (GoogleSheetsRefreshTokenLabel == null)
+ {
+ return;
+ }
+
+ bool isAuthorized = string.Equals(GoogleSheetsRefreshTokenLabel.Text, "Authorized", StringComparison.OrdinalIgnoreCase);
+ GoogleSheetsRefreshTokenLabel.Foreground = GetThemedStatusBrush(isAuthorized);
+ }
+
private void LoadSavedSettings()
{
try
@@ -285,8 +311,7 @@ private void SavedMessage()
private void buttonWikiPage_Click(object sender, RequestNavigateEventArgs e)
{
- Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) { UseShellExecute = true });
- e.Handled = true;
+ ToolWindowNavigation.HandleRequestNavigate(e);
}
private void ButtonSaveSmtpSettings_Click(object sender, RoutedEventArgs e)
@@ -370,7 +395,7 @@ private async void button_AuthorizeGoogleSheets_Click(object sender, RoutedEvent
try
{
string authorizationUrl = GoogleSheetsExport.BuildAuthorizationUrl(settings);
- Process.Start(new ProcessStartInfo(authorizationUrl) { UseShellExecute = true });
+ ToolWindowNavigation.OpenExternalUrl(authorizationUrl);
string authorizationCode = Interaction.InputBox("Paste the authorization code provided by Google after granting access.", "Google Sheets Authorization");
if (string.IsNullOrWhiteSpace(authorizationCode))
@@ -413,19 +438,18 @@ private void UpdateGoogleSheetsStatus(string refreshToken)
if (string.IsNullOrWhiteSpace(refreshToken))
{
GoogleSheetsRefreshTokenLabel.Text = "Not authorized";
- GoogleSheetsRefreshTokenLabel.Foreground = new SolidColorBrush(Colors.DarkRed);
+ GoogleSheetsRefreshTokenLabel.Foreground = GetThemedStatusBrush(false);
}
else
{
GoogleSheetsRefreshTokenLabel.Text = "Authorized";
- GoogleSheetsRefreshTokenLabel.Foreground = new SolidColorBrush(Colors.DarkGreen);
+ GoogleSheetsRefreshTokenLabel.Foreground = GetThemedStatusBrush(true);
}
}
private void Hyperlink_RequestNavigateFormatQueryWiki(object sender, RequestNavigateEventArgs e)
{
- Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) { UseShellExecute = true });
- e.Handled = true;
+ ToolWindowNavigation.HandleRequestNavigate(e);
}
private void Button_SaveOpenAi_Click(object sender, RoutedEventArgs e)
diff --git a/AxialSqlTools/source.extension.vsixmanifest b/AxialSqlTools/source.extension.vsixmanifest
index 00dbdb2..7a0add2 100644
--- a/AxialSqlTools/source.extension.vsixmanifest
+++ b/AxialSqlTools/source.extension.vsixmanifest
@@ -10,7 +10,7 @@
Resources\vsix-logo.png
Resources\vsix-logo.png
-
+
amd64