Merge pull request #7920 from microsoft/users/niels9001/fluent-imageresizer

[Image Resizer] Fluent UI and theming support
This commit is contained in:
Clint Rutkas 2020-11-16 10:47:42 -08:00 committed by GitHub
commit d649ed70e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 812 additions and 244 deletions

View File

@ -1364,6 +1364,7 @@ MMI
mockapi
MODECHANGE
moderncop
modernwpf
modulekey
MONITORINFO
MONITORINFOEX

View File

@ -485,12 +485,16 @@
<File Source="$(var.BinX64Dir)modules\$(var.ImageResizerProjectName)\ImageResizer.exe">
<netfx:NativeImage Id="ImageResizer.exe" Platform="all" Priority="0" />
</File>
<File Source="$(var.BinX64Dir)modules\$(var.ImageResizerProjectName)\ImageResizerExt.dll" KeyPath="yes" />
<File Source="$(var.BinX64Dir)modules\$(var.ImageResizerProjectName)\Newtonsoft.Json.dll" />
<File Source="$(var.BinX64Dir)modules\$(var.ImageResizerProjectName)\ImageResizer.dll" />
<File Source="$(var.BinX64Dir)modules\$(var.ImageResizerProjectName)\ImageResizer.deps.json" />
<File Source="$(var.BinX64Dir)modules\$(var.ImageResizerProjectName)\ImageResizer.runtimeconfig.json" />
<File Id="Module_ImageResizer_ControlzEX" Source="$(var.BinX64Dir)modules\$(var.ImageResizerProjectName)\ControlzEx.dll" />
<File Id="Module_ImageResizer_ModernWpf_Controls" Source="$(var.BinX64Dir)modules\$(var.ImageResizerProjectName)\ModernWpf.Controls.dll" />
<File Id="Module_ImageResizer_ModernWpf" Source="$(var.BinX64Dir)modules\$(var.ImageResizerProjectName)\ModernWpf.dll" />
<File Id="Module_ImageResizer_System_Text_Json" Source="$(var.BinX64Dir)modules\$(var.ImageResizerProjectName)\System.Text.Json.dll" />
<File Id="Module_ImageResizer_Microsoft_Xaml_Behaviors" Source="$(var.BinX64Dir)modules\$(var.ImageResizerProjectName)\Microsoft.Xaml.Behaviors.dll" />
<File Source="$(var.BinX64Dir)modules\$(var.ImageResizerProjectName)\ImageResizerExt.dll" KeyPath="yes" />
<File Id="ImageResizer_interop" Source="$(var.BinX64Dir)modules\$(var.ImageResizerProjectName)\PowerToysInterop.dll" />
<File Id="ImageResizer_System.IO.Abstractions.dll" Source="$(var.BinX64Dir)modules\$(var.ImageResizerProjectName)\System.IO.Abstractions.dll" />

View File

@ -26,6 +26,7 @@ namespace ImageResizer.Properties
{
if (disposing)
{
_imageResizerApp.Dispose();
_imageResizerApp = null;
}

View File

@ -3,74 +3,36 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:m="clr-namespace:ImageResizer.Models"
xmlns:sys="clr-namespace:System;assembly=System.Runtime"
xmlns:v="clr-namespace:ImageResizer.Views">
xmlns:v="clr-namespace:ImageResizer.Views"
xmlns:ui="http://schemas.modernwpf.com/2019">
<Application.Resources>
<ObjectDataProvider x:Key="ResizeFitValues"
MethodName="GetValues"
ObjectType="sys:Enum">
<ObjectDataProvider.MethodParameters>
<x:Type Type="{x:Type m:ResizeFit}"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<ObjectDataProvider x:Key="ResizeUnitValues"
MethodName="GetValues"
ObjectType="sys:Enum">
<ObjectDataProvider.MethodParameters>
<x:Type Type="{x:Type m:ResizeUnit}"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<v:EnumValueConverter x:Key="EnumValueConverter"/>
<v:AutoDoubleConverter x:Key="AutoDoubleConverter"/>
<v:BoolValueConverter x:Key="BoolValueConverter"/>
<v:VisibilityBoolConverter x:Key="VisibilityBoolConverter"/>
<Style x:Key="MainInstructionTextBlockStyle" TargetType="TextBlock">
<Setter Property="FontSize" Value="12pt"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HotTrackColor}}"/>
</Style>
<Style TargetType="TextBox">
<Setter Property="VerticalContentAlignment" Value="Center"/>
</Style>
<Style x:Key="AccessibleComboBoxStyle" TargetType="ComboBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBoxItem}">
<Border Name="SelectedItemBorder"
Padding="2"
SnapsToDevicePixels="true">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="SelectedItemBorder"
Property="Background"
Value="#FF91b9d8"/>
<Setter Property="Foreground"
Value="Black" />
</Trigger>
<Trigger Property="IsHighlighted" Value="true">
<Setter TargetName="SelectedItemBorder"
Property="Background"
Value="#FFdadada" />
<Setter Property="Foreground"
Value="Black" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true" />
<Condition Property="IsHighlighted" Value="true" />
</MultiTrigger.Conditions>
<Setter TargetName="SelectedItemBorder"
Property="Background"
Value="#FF619ccb"/>
<Setter Property="Foreground"
Value="Black" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ui:ThemeResources />
<ui:XamlControlsResources />
</ResourceDictionary.MergedDictionaries>
<ObjectDataProvider x:Key="ResizeFitValues"
MethodName="GetValues"
ObjectType="sys:Enum">
<ObjectDataProvider.MethodParameters>
<x:Type Type="{x:Type m:ResizeFit}"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<ObjectDataProvider x:Key="ResizeUnitValues"
MethodName="GetValues"
ObjectType="sys:Enum">
<ObjectDataProvider.MethodParameters>
<x:Type Type="{x:Type m:ResizeUnit}"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<v:EnumValueConverter x:Key="EnumValueConverter"/>
<v:AutoDoubleConverter x:Key="AutoDoubleConverter"/>
<v:BoolValueConverter x:Key="BoolValueConverter"/>
<v:VisibilityBoolConverter x:Key="VisibilityBoolConverter"/>
</ResourceDictionary>
</Application.Resources>
</Application>

View File

@ -13,8 +13,11 @@ using ImageResizer.Views;
namespace ImageResizer
{
public partial class App : Application
public partial class App : Application, IDisposable
{
private ThemeManager _themeManager;
private bool _isDisposed;
static App()
{
Console.InputEncoding = Encoding.Unicode;
@ -28,6 +31,8 @@ namespace ImageResizer
var mainWindow = new MainWindow(new MainViewModel(batch, Settings.Default));
mainWindow.Show();
_themeManager = new ThemeManager(this);
// Temporary workaround for issue #1273
BecomeForegroundWindow(new System.Windows.Interop.WindowInteropHelper(mainWindow).Handle);
}
@ -39,5 +44,27 @@ namespace ImageResizer
_ = NativeMethods.SendInput(1, inputs, NativeMethods.INPUT.Size);
NativeMethods.SetForegroundWindow(hWnd);
}
protected virtual void Dispose(bool disposing)
{
if (!_isDisposed)
{
if (disposing)
{
_themeManager?.Dispose();
}
// TODO: free unmanaged resources (unmanaged objects) and override finalizer
// TODO: set large fields to null
_isDisposed = true;
}
}
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}

View File

@ -61,10 +61,12 @@
<Resource Include="Resources\ImageResizer.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="ControlzEx" Version="4.4.0" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.0">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.19" />
<PackageReference Include="ModernWpfUI" Version="0.9.2" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
<PrivateAssets>all</PrivateAssets>

View File

@ -105,6 +105,15 @@ namespace ImageResizer.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Fallback encoder.
/// </summary>
public static string Advanced_FallbackEncoder_Name {
get {
return ResourceManager.GetString("Advanced_FallbackEncoder_Name", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to File.
/// </summary>
@ -123,6 +132,15 @@ namespace ImageResizer.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Filename.
/// </summary>
public static string Advanced_FileName_Name {
get {
return ResourceManager.GetString("Advanced_FileName_Name", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Original filename.
/// </summary>
@ -195,6 +213,15 @@ namespace ImageResizer.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to JPEG quality level.
/// </summary>
public static string Advanced_JpegQualityLevel_Name {
get {
return ResourceManager.GetString("Advanced_JpegQualityLevel_Name", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to _Use original date modified.
/// </summary>
@ -213,6 +240,15 @@ namespace ImageResizer.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to PNG interlacing.
/// </summary>
public static string Advanced_PngInterlaceOption_Name {
get {
return ResourceManager.GetString("Advanced_PngInterlaceOption_Name", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Sizes.
/// </summary>
@ -232,7 +268,16 @@ namespace ImageResizer.Properties {
}
/// <summary>
/// Looks up a localized string similar to Advanced Options.
/// Looks up a localized string similar to TIFF compression.
/// </summary>
public static string Advanced_TiffCompressOption_Name {
get {
return ResourceManager.GetString("Advanced_TiffCompressOption_Name", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Settings.
/// </summary>
public static string Advanced_Title {
get {
@ -259,7 +304,7 @@ namespace ImageResizer.Properties {
}
/// <summary>
/// Looks up a localized string similar to © 2019 Brice Lambson. All rights reserved..
/// Looks up a localized string similar to © 2020 Brice Lambson. All rights reserved..
/// </summary>
public static string Copyright {
get {
@ -268,7 +313,16 @@ namespace ImageResizer.Properties {
}
/// <summary>
/// Looks up a localized string similar to Image Resizer for Windows.
/// Looks up a localized string similar to Height.
/// </summary>
public static string Height {
get {
return ResourceManager.GetString("Height", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Image Resizer.
/// </summary>
public static string ImageResizer {
get {
@ -286,7 +340,7 @@ namespace ImageResizer.Properties {
}
/// <summary>
/// Looks up a localized string similar to _Select a size..
/// Looks up a localized string similar to _Select a size.
/// </summary>
public static string Input_Content {
get {
@ -312,15 +366,6 @@ namespace ImageResizer.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Resize your pictures.
/// </summary>
public static string Input_MainInstruction {
get {
return ResourceManager.GetString("Input_MainInstruction", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to R_esize the original pictures (don&apos;t create copies).
/// </summary>
@ -340,7 +385,7 @@ namespace ImageResizer.Properties {
}
/// <summary>
/// Looks up a localized string similar to Advanced options....
/// Looks up a localized string similar to Settings.
/// </summary>
public static string Input_ShowAdvanced {
get {
@ -384,6 +429,15 @@ namespace ImageResizer.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Apply settings.
/// </summary>
public static string OK_Tooltip {
get {
return ResourceManager.GetString("OK_Tooltip", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Phone.
/// </summary>
@ -537,6 +591,24 @@ namespace ImageResizer.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Resize pictures.
/// </summary>
public static string Resize_Tooltip {
get {
return ResourceManager.GetString("Resize_Tooltip", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Resize type.
/// </summary>
public static string Resize_Type {
get {
return ResourceManager.GetString("Resize_Type", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Fill.
/// </summary>
@ -717,6 +789,24 @@ namespace ImageResizer.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Times Symbol.
/// </summary>
public static string Times_Symbol {
get {
return ResourceManager.GetString("Times_Symbol", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Unit.
/// </summary>
public static string Unit {
get {
return ResourceManager.GetString("Unit", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Value must be between &apos;{0}&apos; and &apos;{1}&apos;..
/// </summary>
@ -734,5 +824,14 @@ namespace ImageResizer.Properties {
return ResourceManager.GetString("Version", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Width.
/// </summary>
public static string Width {
get {
return ResourceManager.GetString("Width", resourceCulture);
}
}
}
}

View File

@ -125,15 +125,21 @@
</data>
<data name="Advanced_DeleteSize" xml:space="preserve">
<value>Delete</value>
<comment>remove a file</comment>
</data>
<data name="Advanced_Encoding" xml:space="preserve">
<value>Encoding</value>
<comment>encoding a file to a different format</comment>
</data>
<data name="Advanced_FallbackEncoder" xml:space="preserve">
<value>_Fallback encoder:</value>
</data>
<data name="Advanced_FallbackEncoder_Name" xml:space="preserve">
<value>Fallback encoder</value>
</data>
<data name="Advanced_File" xml:space="preserve">
<value>File</value>
<comment>as in file name</comment>
</data>
<data name="Advanced_FileName" xml:space="preserve">
<value>_Filename:</value>
@ -159,21 +165,33 @@
<data name="Advanced_FileNameTokens" xml:space="preserve">
<value>The following parameters can be used.</value>
</data>
<data name="Advanced_FileName_Name" xml:space="preserve">
<value>Filename</value>
</data>
<data name="Advanced_JpegQualityLevel" xml:space="preserve">
<value>_JPEG quality level:</value>
</data>
<data name="Advanced_JpegQualityLevel_Name" xml:space="preserve">
<value>JPEG quality level</value>
</data>
<data name="Advanced_KeepDateModified" xml:space="preserve">
<value>_Use original date modified</value>
</data>
<data name="Advanced_PngInterlaceOption" xml:space="preserve">
<value>_PNG interlacing:</value>
</data>
<data name="Advanced_PngInterlaceOption_Name" xml:space="preserve">
<value>PNG interlacing</value>
</data>
<data name="Advanced_Sizes" xml:space="preserve">
<value>Sizes</value>
</data>
<data name="Advanced_TiffCompressOption" xml:space="preserve">
<value>_TIFF compression:</value>
</data>
<data name="Advanced_TiffCompressOption_Name" xml:space="preserve">
<value>TIFF compression</value>
</data>
<data name="Advanced_Title" xml:space="preserve">
<value>Settings</value>
</data>
@ -184,16 +202,20 @@
<value>Cancel</value>
</data>
<data name="Copyright" xml:space="preserve">
<value>© 2019 Brice Lambson. All rights reserved.</value>
<value>© 2020 Brice Lambson. All rights reserved.</value>
</data>
<data name="Height" xml:space="preserve">
<value>Height</value>
</data>
<data name="ImageResizer" xml:space="preserve">
<value>Image Resizer</value>
<comment>Product name, do not loc</comment>
</data>
<data name="Input_Auto" xml:space="preserve">
<value>(auto)</value>
</data>
<data name="Input_Content" xml:space="preserve">
<value>_Select a size.</value>
<value>_Select a size</value>
</data>
<data name="Input_Custom" xml:space="preserve">
<value>Custom</value>
@ -201,9 +223,6 @@
<data name="Input_IgnoreOrientation" xml:space="preserve">
<value>Ign_ore the orientation of pictures</value>
</data>
<data name="Input_MainInstruction" xml:space="preserve">
<value>Resize your pictures</value>
</data>
<data name="Input_Replace" xml:space="preserve">
<value>R_esize the original pictures (don't create copies)</value>
</data>
@ -225,6 +244,9 @@
<data name="OK" xml:space="preserve">
<value>OK</value>
</data>
<data name="OK_Tooltip" xml:space="preserve">
<value>Apply settings</value>
</data>
<data name="Phone" xml:space="preserve">
<value>Phone</value>
</data>
@ -306,6 +328,12 @@
<data name="ResizeUnit_Pixel" xml:space="preserve">
<value>Pixels</value>
</data>
<data name="Resize_Tooltip" xml:space="preserve">
<value>Resize pictures</value>
</data>
<data name="Resize_Type" xml:space="preserve">
<value>Resize type</value>
</data>
<data name="Results_Close" xml:space="preserve">
<value>Close</value>
</data>
@ -336,10 +364,19 @@
<data name="TiffCompressOption_Zip" xml:space="preserve">
<value>Zip</value>
</data>
<data name="Times_Symbol" xml:space="preserve">
<value>Times Symbol</value>
</data>
<data name="Unit" xml:space="preserve">
<value>Unit</value>
</data>
<data name="ValueMustBeBetween" xml:space="preserve">
<value>Value must be between '{0}' and '{1}'.</value>
</data>
<data name="Version" xml:space="preserve">
<value>Version</value>
</data>
<data name="Width" xml:space="preserve">
<value>Width</value>
</data>
</root>

View File

@ -0,0 +1,18 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=System.Runtime">
<!-- Metadata -->
<system:String x:Key="Theme.Name">Dark.Accent1</system:String>
<system:String x:Key="Theme.Origin">PowerToysImageResizer</system:String>
<system:String x:Key="Theme.DisplayName">Accent1 (Dark)</system:String>
<system:String x:Key="Theme.BaseColorScheme">Dark</system:String>
<system:String x:Key="Theme.ColorScheme">Accent1</system:String>
<Color x:Key="Theme.PrimaryAccentColor">Black</Color>
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FF3a3a3a" />
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FF333333" />
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FFFFFFFF" />
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF999999" />
<SolidColorBrush x:Key="PrimaryBorderBrush" Color="Transparent"/>
</ResourceDictionary>

View File

@ -0,0 +1,18 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=System.Runtime">
<!-- Metadata -->
<system:String x:Key="Theme.Name">HighContrast.Accent2</system:String>
<system:String x:Key="Theme.Origin">PowerToysImageResizer</system:String>
<system:String x:Key="Theme.DisplayName">Accent2 (HighContrast)</system:String>
<system:String x:Key="Theme.BaseColorScheme">HighContrast</system:String>
<system:String x:Key="Theme.ColorScheme">Accent2</system:String>
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FF3a3a3a" />
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FF333333" />
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FFffff00" />
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF00ff00" />
<SolidColorBrush x:Key="PrimaryBorderBrush" Color="#FFffff00"/>
</ResourceDictionary>

View File

@ -0,0 +1,19 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=System.Runtime">
<!-- Metadata -->
<system:String x:Key="Theme.Name">HighContrast.Accent3</system:String>
<system:String x:Key="Theme.Origin">PowerToysImageResizer</system:String>
<system:String x:Key="Theme.DisplayName">Accent3 (HighContrast)</system:String>
<system:String x:Key="Theme.BaseColorScheme">HighContrast</system:String>
<system:String x:Key="Theme.ColorScheme">Accent3</system:String>
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FF3a3a3a" />
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FF333333" />
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FF00ff00" />
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FFc0c0c0" />
<SolidColorBrush x:Key="PrimaryBorderBrush" Color="#FF00ff00"/>
</ResourceDictionary>

View File

@ -0,0 +1,18 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=System.Runtime">
<!-- Metadata -->
<system:String x:Key="Theme.Name">HighContrast.Accent4</system:String>
<system:String x:Key="Theme.Origin">PowerToysImageResizer</system:String>
<system:String x:Key="Theme.DisplayName">Accent4 (HighContrast)</system:String>
<system:String x:Key="Theme.BaseColorScheme">HighContrast</system:String>
<system:String x:Key="Theme.ColorScheme">Accent4</system:String>
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FF3a3a3a" />
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FF333333" />
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FFffffff" />
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF1aebff" />
<SolidColorBrush x:Key="PrimaryBorderBrush" Color="White"/>
</ResourceDictionary>

View File

@ -0,0 +1,18 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=System.Runtime">
<!-- Metadata -->
<system:String x:Key="Theme.Name">HighContrast.Accent5</system:String>
<system:String x:Key="Theme.Origin">PowerToysImageResizer</system:String>
<system:String x:Key="Theme.DisplayName">Accent5 (HighContrast)</system:String>
<system:String x:Key="Theme.BaseColorScheme">HighContrast</system:String>
<system:String x:Key="Theme.ColorScheme">Accent5</system:String>
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FFe5e5e5" />
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FFf5f5f5" />
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FF000000" />
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF676666" />
<SolidColorBrush x:Key="PrimaryBorderBrush" Color="Black"/>
</ResourceDictionary>

View File

@ -0,0 +1,18 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=System.Runtime">
<!-- Metadata -->
<system:String x:Key="Theme.Name">Light.Accent1</system:String>
<system:String x:Key="Theme.Origin">PowerToysImageResizer</system:String>
<system:String x:Key="Theme.DisplayName">Accent1 (Light)</system:String>
<system:String x:Key="Theme.BaseColorScheme">Light</system:String>
<system:String x:Key="Theme.ColorScheme">Accent1</system:String>
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FFe5e5e5" />
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FFf5f5f5" />
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FF000000" />
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF676666" />
<SolidColorBrush x:Key="PrimaryBorderBrush" Color="Transparent"/>
</ResourceDictionary>

View File

@ -0,0 +1,24 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using ControlzEx.Theming;
namespace ImageResizer.Utilities
{
public class CustomLibraryThemeProvider : LibraryThemeProvider
{
public static readonly CustomLibraryThemeProvider DefaultInstance = new CustomLibraryThemeProvider();
public CustomLibraryThemeProvider()
: base(true)
{
}
/// <inheritdoc />
public override void FillColorSchemeValues(Dictionary<string, string> values, RuntimeThemeColorValues colorValues)
{
}
}
}

View File

@ -0,0 +1,201 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Linq;
using System.Windows;
using ControlzEx.Theming;
using Microsoft.Win32;
namespace ImageResizer.Utilities
{
public class ThemeManager : IDisposable
{
private readonly Application _app;
private const string LightTheme = "Light.Accent1";
private const string DarkTheme = "Dark.Accent1";
private const string HighContrastOneTheme = "HighContrast.Accent2";
private const string HighContrastTwoTheme = "HighContrast.Accent3";
private const string HighContrastBlackTheme = "HighContrast.Accent4";
private const string HighContrastWhiteTheme = "HighContrast.Accent5";
private Theme currentTheme;
private bool _disposed;
public event ThemeChangedHandler ThemeChanged;
public ThemeManager(Application app)
{
_app = app;
Uri highContrastOneThemeUri = new Uri("pack://application:,,,/Themes/HighContrast1.xaml");
Uri highContrastTwoThemeUri = new Uri("pack://application:,,,/Themes/HighContrast2.xaml");
Uri highContrastBlackThemeUri = new Uri("pack://application:,,,/Themes/HighContrastWhite.xaml");
Uri highContrastWhiteThemeUri = new Uri("pack://application:,,,/Themes/HighContrastBlack.xaml");
Uri lightThemeUri = new Uri("pack://application:,,,/Themes/Light.xaml");
Uri darkThemeUri = new Uri("pack://application:,,,/Themes/Dark.xaml");
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
new LibraryTheme(
highContrastOneThemeUri,
CustomLibraryThemeProvider.DefaultInstance));
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
new LibraryTheme(
highContrastTwoThemeUri,
CustomLibraryThemeProvider.DefaultInstance));
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
new LibraryTheme(
highContrastBlackThemeUri,
CustomLibraryThemeProvider.DefaultInstance));
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
new LibraryTheme(
highContrastWhiteThemeUri,
CustomLibraryThemeProvider.DefaultInstance));
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
new LibraryTheme(
lightThemeUri,
CustomLibraryThemeProvider.DefaultInstance));
ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme(
new LibraryTheme(
darkThemeUri,
CustomLibraryThemeProvider.DefaultInstance));
ResetTheme();
ControlzEx.Theming.ThemeManager.Current.ThemeSyncMode = ThemeSyncMode.SyncWithAppMode;
ControlzEx.Theming.ThemeManager.Current.ThemeChanged += Current_ThemeChanged;
SystemParameters.StaticPropertyChanged += SystemParameters_StaticPropertyChanged;
}
private void SystemParameters_StaticPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(SystemParameters.HighContrast))
{
ResetTheme();
}
}
public Theme GetCurrentTheme()
{
return currentTheme;
}
private static Theme GetHighContrastBaseType()
{
string registryKey = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes";
string theme = (string)Registry.GetValue(registryKey, "CurrentTheme", string.Empty);
theme = theme.Split('\\').Last().Split('.').First().ToString();
switch (theme)
{
case "hc1":
return Theme.HighContrastOne;
case "hc2":
return Theme.HighContrastTwo;
case "hcwhite":
return Theme.HighContrastWhite;
case "hcblack":
return Theme.HighContrastBlack;
default:
return Theme.None;
}
}
private void ResetTheme()
{
if (SystemParameters.HighContrast)
{
Theme highContrastBaseType = GetHighContrastBaseType();
ChangeTheme(highContrastBaseType);
}
else
{
string baseColor = WindowsThemeHelper.GetWindowsBaseColor();
ChangeTheme((Theme)Enum.Parse(typeof(Theme), baseColor));
}
}
private void ChangeTheme(Theme theme)
{
Theme oldTheme = currentTheme;
if (theme == currentTheme)
{
return;
}
if (theme == Theme.HighContrastOne)
{
ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastOneTheme);
currentTheme = Theme.HighContrastOne;
}
else if (theme == Theme.HighContrastTwo)
{
ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastTwoTheme);
currentTheme = Theme.HighContrastTwo;
}
else if (theme == Theme.HighContrastWhite)
{
ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastWhiteTheme);
currentTheme = Theme.HighContrastWhite;
}
else if (theme == Theme.HighContrastBlack)
{
ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastBlackTheme);
currentTheme = Theme.HighContrastBlack;
}
else if (theme == Theme.Light)
{
ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, LightTheme);
currentTheme = Theme.Light;
}
else if (theme == Theme.Dark)
{
ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, DarkTheme);
currentTheme = Theme.Dark;
}
else
{
currentTheme = Theme.None;
}
ThemeChanged?.Invoke(oldTheme, currentTheme);
}
private void Current_ThemeChanged(object sender, ThemeChangedEventArgs e)
{
ResetTheme();
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
ControlzEx.Theming.ThemeManager.Current.ThemeChanged -= Current_ThemeChanged;
SystemParameters.StaticPropertyChanged -= SystemParameters_StaticPropertyChanged;
_disposed = true;
}
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
public delegate void ThemeChangedHandler(Theme oldTheme, Theme newTheme);
public enum Theme
{
None,
Light,
Dark,
HighContrastOne,
HighContrastTwo,
HighContrastBlack,
HighContrastWhite,
}
}

View File

@ -5,9 +5,13 @@
xmlns:m="clr-namespace:ImageResizer.Models"
xmlns:p="clr-namespace:ImageResizer.Properties"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
MinWidth="390"
xmlns:ui="http://schemas.modernwpf.com/2019"
ContentRendered="WindowContentRendered"
MinWidth="560"
MinHeight="340"
Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
ui:WindowHelper.UseModernWindowStyle="True"
ui:TitleBar.IsIconVisible="True"
Background="{DynamicResource PrimaryBackgroundBrush}"
Name="_this"
ResizeMode="NoResize"
SizeToContent="WidthAndHeight"
@ -33,19 +37,19 @@
<local:ContainerFormatConverter x:Key="ContainerFormatConverter"/>
</Window.Resources>
<Grid Margin="11">
<Grid Margin="0">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TabControl>
<TabControl Style="{StaticResource TabControlPivotStyle}">
<TabItem Header="{x:Static p:Resources.Advanced_Sizes}">
<StackPanel Margin="11">
<StackPanel Margin="0,12,0,12">
<!-- TODO: Allow these to be drag-and-drop reordered (issue #15) -->
<ItemsControl Grid.IsSharedSizeScope="True" ItemsSource="{Binding Settings.Sizes}">
<ItemsControl Grid.IsSharedSizeScope="True" TabIndex="0" ItemsSource="{Binding Settings.Sizes}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="m:ResizeSize">
<Grid Margin="0,0,0,7">
<Grid Margin="0,0,0,8">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="0"/>
<ColumnDefinition SharedSizeGroup="1"/>
@ -55,11 +59,16 @@
<ColumnDefinition SharedSizeGroup="5"/>
<ColumnDefinition SharedSizeGroup="6"/>
</Grid.ColumnDefinitions>
<TextBox Width="66" Text="{Binding Name}"/>
<TextBox Width="96"
MaxWidth="96"
TextWrapping="Wrap"
AutomationProperties.Name="{Binding Name}"
Text="{Binding Name}"/>
<ComboBox Grid.Column="1"
Height="23"
Margin="5,0,0,0"
Margin="8,0,0,0"
Width="90"
ItemsSource="{Binding Source={StaticResource ResizeFitValues}}"
AutomationProperties.Name="{x:Static p:Resources.Resize_Type}"
SelectedItem="{Binding Fit}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type m:ResizeFit}">
@ -68,9 +77,11 @@
</ComboBox.ItemTemplate>
</ComboBox>
<TextBox Grid.Column="2"
Width="43"
Height="23"
Margin="7,0,0,0">
Width="56"
MaxWidth="56"
TextWrapping="Wrap"
AutomationProperties.Name="{x:Static p:Resources.Width}"
Margin="8,0,0,0">
<TextBox.Text>
<Binding Converter="{StaticResource AutoDoubleConverter}"
Path="Width"
@ -82,15 +93,20 @@
</TextBox.Text>
</TextBox>
<TextBlock Grid.Column="3"
Margin="5,0,0,0"
Foreground="{DynamicResource PrimaryForegroundBrush}"
Name="Times_Symbol"
AutomationProperties.Name="{x:Static p:Resources.Times_Symbol}"
VerticalAlignment="Center"
Visibility="{Binding ShowHeight,Converter={StaticResource BoolValueConverter}}">
×
</TextBlock>
Text="&#xE711;"
FontFamily="Segoe MDL2 Assets"
Width="25"
TextAlignment="Center"
Visibility="{Binding ShowHeight,Converter={StaticResource BoolValueConverter}}"/>
<TextBox Grid.Column="4"
Width="43"
Height="23"
Margin="5,0,0,0"
Width="56"
MaxWidth="56"
TextWrapping="Wrap"
AutomationProperties.Name="{x:Static p:Resources.Height}"
Visibility="{Binding ShowHeight,Converter={StaticResource BoolValueConverter}}">
<TextBox.Text>
<Binding Converter="{StaticResource AutoDoubleConverter}"
@ -103,9 +119,10 @@
</TextBox.Text>
</TextBox>
<ComboBox Grid.Column="5"
Height="23"
Margin="7,0,0,0"
Margin="8,0,0,0"
MinWidth="120"
ItemsSource="{Binding Source={StaticResource ResizeUnitValues}}"
AutomationProperties.Name="{x:Static p:Resources.Unit}"
SelectedItem="{Binding Unit}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type m:ResizeUnit}">
@ -113,24 +130,27 @@
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Grid.Column="6" Margin="5,0,0,0" VerticalAlignment="Center">
<local:AccessibleHyperlink ControlType="Button" Command="{Binding DataContext.RemoveSizeCommand,ElementName=_this}" CommandParameter="{Binding}">
<Run Text="{x:Static p:Resources.Advanced_DeleteSize}"/>
</local:AccessibleHyperlink>
</TextBlock>
<Button Content="&#xE107;"
FontFamily="Segoe MDL2 Assets"
Background="Transparent"
Grid.Column="6"
Margin="8,0,0,0"
VerticalAlignment="Center"
AutomationProperties.Name="{x:Static p:Resources.Advanced_DeleteSize}"
ToolTip="{x:Static p:Resources.Advanced_DeleteSize}"
Command="{Binding DataContext.RemoveSizeCommand,ElementName=_this}"
CommandParameter="{Binding}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock>
<local:AccessibleHyperlink ControlType="Button" Command="{Binding AddSizeCommand}">
<Run Text="{x:Static p:Resources.Advanced_CreateSize}"/>
</local:AccessibleHyperlink>
</TextBlock>
<Button Margin="0,12,0,0"
Command="{Binding AddSizeCommand}"
Content="{x:Static p:Resources.Advanced_CreateSize}"/>
</StackPanel>
</TabItem>
<TabItem Header="{x:Static p:Resources.Advanced_Encoding}">
<Grid Margin="11" VerticalAlignment="Top">
<Grid Margin="0,12,0,12" VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
@ -142,12 +162,13 @@
<RowDefinition/>
</Grid.RowDefinitions>
<Label Content="{x:Static p:Resources.Advanced_FallbackEncoder}"
Padding="0,5,5,0"
Padding="0,8,8,0"
Target="{Binding ElementName=_fallbackEncoderComboBox}"/>
<ComboBox Grid.Column="1"
Height="23"
HorizontalAlignment="Left"
MinWidth="148"
ItemsSource="{Binding Encoders}"
AutomationProperties.Name="{x:Static p:Resources.Advanced_FallbackEncoder_Name}"
Name="_fallbackEncoderComboBox"
SelectedItem="{Binding Settings.FallbackEncoder}">
<ComboBox.ItemTemplate>
@ -157,28 +178,31 @@
</ComboBox.ItemTemplate>
</ComboBox>
<Label Grid.Row="1"
Margin="0,7,0,0"
Margin="0,8,0,0"
Content="{x:Static p:Resources.Advanced_JpegQualityLevel}"
Padding="0,5,5,0"
Padding="0,8,8,0"
Target="{Binding ElementName=_jpegQualityLevelTextBox}"/>
<TextBox Grid.Row="1"
Grid.Column="1"
Width="34"
Height="23"
Margin="0,7,0,0"
Width="56"
MinWidth="148"
TextWrapping="Wrap"
AutomationProperties.Name="{x:Static p:Resources.Advanced_JpegQualityLevel_Name}"
Margin="0,8,0,0"
HorizontalAlignment="Left"
Name="_jpegQualityLevelTextBox"
Text="{Binding Settings.JpegQualityLevel,ValidatesOnExceptions=True,ValidatesOnDataErrors=True}"/>
<Label Grid.Row="2"
Margin="0,7,0,0"
Margin="0,8,0,0"
Content="{x:Static p:Resources.Advanced_PngInterlaceOption}"
Padding="0,5,5,0"
Padding="0,8,8,0"
Target="{Binding ElementName=_pngInterlaceComboBox}"/>
<ComboBox Grid.Row="2"
Grid.Column="1"
Height="23"
Margin="0,7,0,0"
Margin="0,8,0,0"
MinWidth="148"
HorizontalAlignment="Left"
AutomationProperties.Name="{x:Static p:Resources.Advanced_PngInterlaceOption_Name}"
ItemsSource="{Binding Source={StaticResource PngInterlaceOptionValues}}"
Name="_pngInterlaceComboBox"
SelectedItem="{Binding Settings.PngInterlaceOption}">
@ -189,15 +213,16 @@
</ComboBox.ItemTemplate>
</ComboBox>
<Label Grid.Row="3"
Margin="0,7,0,0"
Margin="0,8,0,0"
Content="{x:Static p:Resources.Advanced_TiffCompressOption}"
Padding="0,5,5,0"
Padding="0,8,8,0"
Target="{Binding ElementName=_tiffCompressComboBox}"/>
<ComboBox Grid.Row="3"
Grid.Column="1"
Height="23"
Margin="0,7,0,0"
MinWidth="148"
Margin="0,8,0,0"
HorizontalAlignment="Left"
AutomationProperties.Name="{x:Static p:Resources.Advanced_TiffCompressOption_Name}"
ItemsSource="{Binding Source={StaticResource TiffCompressOptionValues}}"
Name="_tiffCompressComboBox"
SelectedItem="{Binding Settings.TiffCompressOption}">
@ -210,9 +235,9 @@
</Grid>
</TabItem>
<TabItem Header="{x:Static p:Resources.Advanced_File}">
<StackPanel Margin="11,9">
<StackPanel Margin="0,12,0,12">
<TextBlock Text="{x:Static p:Resources.Advanced_FileNameTokens}"/>
<TextBlock Margin="9,5,0,0">
<TextBlock Margin="0,8,0,0">
<Run Text="%1 -"/>
<Run Text="{x:Static p:Resources.Advanced_FileNameToken1}"/>
<LineBreak/>
@ -231,42 +256,57 @@
<Run>%6 -</Run>
<Run Text="{x:Static p:Resources.Advanced_FileNameToken6}"/>
</TextBlock>
<Grid Margin="0,7,0,0">
<Grid Margin="0,8,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label HorizontalAlignment="Left"
x:Name="fileNameTextBoxLabel"
Content="{x:Static p:Resources.Advanced_FileName}"
Padding="0,5,5,0"
Target="{Binding ElementName=_fileNameTextBox}"/>
Padding="0,4,4,0"
Target="{Binding ElementName=fileNameTextBox}"/>
<TextBox Grid.Column="1"
Height="23"
Name="_fileNameTextBox"
MinWidth="240"
TabIndex="0"
HorizontalAlignment="Left"
TextWrapping="Wrap"
Name="fileNameTextBox"
AutomationProperties.Name="{x:Static p:Resources.Advanced_FileName_Name}"
Text="{Binding Settings.FileName}"/>
</Grid>
<Separator Margin="0,11,0,0"/>
<CheckBox Margin="0,11,0,0"
<Separator Margin="0,12,0,0"/>
<CheckBox Margin="0,12,0,0"
Content="{x:Static p:Resources.Advanced_KeepDateModified}"
IsChecked="{Binding Settings.KeepDateModified}"/>
</StackPanel>
</TabItem>
</TabControl>
<StackPanel Grid.Row="1"
Margin="0,11,0,0"
<Border Grid.Row="1"
Margin="0,24,0,0"
BorderBrush="{DynamicResource PrimaryBorderBrush}"
BorderThickness="0,1,0,0"
Background="{DynamicResource SecondaryBackgroundBrush}"
Padding="12">
<StackPanel
HorizontalAlignment="Right"
Orientation="Horizontal">
<Button Height="23"
MinWidth="75"
Click="HandleAcceptClick"
Content="{x:Static p:Resources.OK}"
IsDefault="True"/>
<Button Height="23"
MinWidth="75"
Margin="7,0,0,0"
<Button MinWidth="76"
TabIndex="100"
Click="HandleAcceptClick"
Style="{StaticResource AccentButtonStyle}"
Content="{x:Static p:Resources.OK}"
AutomationProperties.Name="{x:Static p:Resources.OK_Tooltip}"
IsDefault="True"/>
<Button MinWidth="76"
Margin="8,0,0,0"
TabIndex="101"
Content="{x:Static p:Resources.Cancel}"
IsCancel="True"/>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</Window>

View File

@ -25,5 +25,11 @@ namespace ImageResizer.Views
Process.Start(e.Uri.ToString());
e.Handled = true;
}
// Fix for black outline WPF bug when a window uses custom chrome. More info here https://stackoverflow.com/questions/29207331/wpf-window-with-custom-chrome-has-unwanted-outline-on-right-and-bottom
private void WindowContentRendered(object sender, System.EventArgs e)
{
InvalidateVisual();
}
}
}

View File

@ -4,27 +4,56 @@
xmlns:local="clr-namespace:ImageResizer.Views"
xmlns:m="clr-namespace:ImageResizer.Models"
xmlns:p="clr-namespace:ImageResizer.Properties"
xmlns:ui="http://schemas.modernwpf.com/2019"
MinWidth="350">
<StackPanel>
<TextBlock Margin="11,11,11,0"
Style="{StaticResource MainInstructionTextBlockStyle}"
Text="{x:Static p:Resources.Input_MainInstruction}"/>
<Label Margin="11,11,11,0"
<UserControl.Resources>
<Style x:Key="DisabledWhenUnselectedComboBoxStyle" TargetType="ComboBox" BasedOn="{StaticResource DefaultComboBoxStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}" Value="True">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}" Value="False">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="DisabledWhenUnselectedTextBoxStyle" TargetType="TextBox" BasedOn="{StaticResource DefaultTextBoxStyle}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}" Value="True">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}" Value="False">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<StackPanel Background="{DynamicResource PrimaryBackgroundBrush}">
<Label Margin="12,12,12,0"
FontSize="16"
Content="{x:Static p:Resources.Input_Content}"
Target="{Binding ElementName=_selectedSizeListBox}"/>
<ListBox Margin="20,0,11,0"
<ListBox Margin="12,24,12,0"
BorderThickness="0"
Background="Transparent"
AutomationProperties.Name="Sizes listbox"
ItemsSource="{Binding Settings.AllSizes}"
Name="_selectedSizeListBox"
SelectedIndex="{Binding Settings.SelectedSizeIndex}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<RadioButton Margin="0,7,0,0"
VerticalContentAlignment="Center"
<RadioButton Margin="0,4,0,0"
VerticalAlignment="Center"
VerticalContentAlignment="Top"
AutomationProperties.Name="{Binding Name}"
Focusable="False"
IsChecked="{Binding IsSelected,RelativeSource={RelativeSource TemplatedParent}}">
<ContentPresenter/>
@ -32,40 +61,46 @@
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="AutomationProperties.Name" Value="{Binding Name}"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.Resources>
<DataTemplate DataType="{x:Type m:ResizeSize}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"/>
<TextBlock Text=" ("/>
<TextBlock Text="{Binding Fit,Converter={StaticResource EnumValueConverter},ConverterParameter=ThirdPersonSingular}"/>
<TextBlock Text=" "/>
<TextBlock Text="{Binding Width,Converter={StaticResource AutoDoubleConverter},ConverterParameter=Auto}"/>
<TextBlock Text=" × " Visibility="{Binding ShowHeight,Converter={StaticResource BoolValueConverter}}"/>
<TextBlock Text="{Binding Height,Converter={StaticResource AutoDoubleConverter},ConverterParameter=Auto}" Visibility="{Binding ShowHeight,Converter={StaticResource BoolValueConverter}}"/>
<TextBlock Text=" "/>
<TextBlock Text="{Binding Unit,Converter={StaticResource EnumValueConverter},ConverterParameter=ToLower}"/>
<TextBlock Text=")"/>
<TextBlock Text="{Binding Name}" FontWeight="SemiBold" Foreground="{DynamicResource PrimaryForegroundBrush}"/>
<TextBlock Text="(" Margin="4,0,0,0" Foreground="{DynamicResource SecondaryForegroundBrush}"/>
<TextBlock Text="{Binding Fit,Converter={StaticResource EnumValueConverter},ConverterParameter=ThirdPersonSingular}" Foreground="{DynamicResource SecondaryForegroundBrush}"/>
<TextBlock Text="{Binding Width,Converter={StaticResource AutoDoubleConverter},ConverterParameter=Auto}" Margin="4,0,0,0" Foreground="{DynamicResource SecondaryForegroundBrush}"/>
<TextBlock Text="&#xE711;" FontSize="11" FontFamily="Segoe MDL2 Assets" Visibility="{Binding ShowHeight,Converter={StaticResource BoolValueConverter}}" Margin="4,5,0,0" Foreground="{DynamicResource SecondaryForegroundBrush}"/>
<TextBlock Text="{Binding Height,Converter={StaticResource AutoDoubleConverter},ConverterParameter=Auto}" Visibility="{Binding ShowHeight,Converter={StaticResource BoolValueConverter}}" Margin="4,0,0,0" Foreground="{DynamicResource SecondaryForegroundBrush}"/>
<TextBlock Text="{Binding Unit,Converter={StaticResource EnumValueConverter},ConverterParameter=ToLower}" Margin="4,0,0,0" Foreground="{DynamicResource SecondaryForegroundBrush}"/>
<TextBlock Text=")" Foreground="{DynamicResource SecondaryForegroundBrush}"/>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type m:CustomSize}">
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" Text="{Binding Name}"/>
<ComboBox Height="23"
Margin="5,0,0,0"
<StackPanel Orientation="Horizontal" Margin="0,-8,0,0">
<TextBlock VerticalAlignment="Center"
Text="{Binding Name}"
Foreground="{DynamicResource PrimaryForegroundBrush}"
FontWeight="SemiBold"/>
<ComboBox Margin="8,0,0,0"
ItemsSource="{Binding Source={StaticResource ResizeFitValues}}"
SelectedItem="{Binding Fit}"
ItemContainerStyle="{StaticResource AccessibleComboBoxStyle}">
Style="{StaticResource DisabledWhenUnselectedComboBoxStyle}"
AutomationProperties.Name="{x:Static p:Resources.Resize_Type}"
SelectedItem="{Binding Fit}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type m:ResizeFit}">
<ContentPresenter Content="{Binding Converter={StaticResource EnumValueConverter}}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBox Width="43"
Height="23"
Margin="7,0,0,0">
<TextBox Width="56"
TextWrapping="Wrap"
Style="{StaticResource DisabledWhenUnselectedTextBoxStyle}"
AutomationProperties.Name="{x:Static p:Resources.Width}"
Margin="8,0,0,0">
<TextBox.Text>
<Binding Converter="{StaticResource AutoDoubleConverter}"
Path="Width"
@ -76,14 +111,20 @@
</Binding>
</TextBox.Text>
</TextBox>
<TextBlock Margin="5,0,0,0"
VerticalAlignment="Center"
Visibility="{Binding ShowHeight,Converter={StaticResource BoolValueConverter}}">
×
</TextBlock>
<TextBox Width="43"
Height="23"
Margin="5,0,0,0"
<TextBlock VerticalAlignment="Center"
Text="&#xE711;"
FontFamily="Segoe MDL2 Assets"
Width="25"
Foreground="{DynamicResource SecondaryForegroundBrush}"
Name="Times_Symbol"
AutomationProperties.Name="{x:Static p:Resources.Times_Symbol}"
TextAlignment="Center"
Visibility="{Binding ShowHeight,Converter={StaticResource BoolValueConverter}}"/>
<TextBox Width="56"
Style="{StaticResource DisabledWhenUnselectedTextBoxStyle}"
TextWrapping="Wrap"
AutomationProperties.Name="{x:Static p:Resources.Height}"
Visibility="{Binding ShowHeight,Converter={StaticResource BoolValueConverter}}">
<TextBox.Text>
<Binding Converter="{StaticResource AutoDoubleConverter}"
@ -95,11 +136,11 @@
</Binding>
</TextBox.Text>
</TextBox>
<ComboBox Height="23"
Margin="7,0,0,0"
<ComboBox Margin="8,0,0,0"
ItemsSource="{Binding Source={StaticResource ResizeUnitValues}}"
SelectedItem="{Binding Unit}"
ItemContainerStyle="{StaticResource AccessibleComboBoxStyle}">
Style="{StaticResource DisabledWhenUnselectedComboBoxStyle}"
AutomationProperties.Name="{x:Static p:Resources.Unit}"
SelectedItem="{Binding Unit}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type m:ResizeUnit}">
<ContentPresenter Content="{Binding Converter={StaticResource EnumValueConverter}}"/>
@ -110,22 +151,25 @@
</DataTemplate>
</ListBox.Resources>
</ListBox>
<CheckBox Margin="11,11,11,0"
<CheckBox Margin="12,36,12,0"
Content="{x:Static p:Resources.Input_ShrinkOnly}"
IsChecked="{Binding Settings.ShrinkOnly}"/>
<!-- TODO: This option doesn't make much sense when resizing into a directory. We should swap it for an option
to overwrite any files in the directory instead (issue #88) -->
<CheckBox Margin="11,7,11,0"
<CheckBox Margin="12,4,12,0"
Content="{x:Static p:Resources.Input_Replace}"
IsChecked="{Binding Settings.Replace}"/>
<CheckBox Margin="11,7,11,0"
<CheckBox Margin="12,4,12,0"
Content="{x:Static p:Resources.Input_IgnoreOrientation}"
IsChecked="{Binding Settings.IgnoreOrientation}"/>
<Border Margin="0,11,0,0"
Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
BorderBrush="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}"
<Border Margin="0,24,0,0"
Background="{DynamicResource SecondaryBackgroundBrush}"
BorderBrush="{DynamicResource PrimaryBorderBrush}"
BorderThickness="0,1,0,0"
Padding="11,11">
Padding="12">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
@ -133,31 +177,34 @@
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="AdvancedSettingsTextBlock"
VerticalAlignment="Center"
Visibility="{Binding ShowAdvancedSettings, Converter={StaticResource BoolValueConverter}}"
IsEnabled="{Binding Visibility,ElementName=AdvancedSettingsTextBlock, Converter={StaticResource VisibilityBoolConverter}}"
Focusable="{Binding Visibility,ElementName=AdvancedSettingsTextBlock, Converter={StaticResource VisibilityBoolConverter}}">
<local:AccessibleHyperlink ControlType="Button" Command="{Binding ShowAdvancedCommand}">
<Run Text="{x:Static p:Resources.Input_ShowAdvanced}"/>
</local:AccessibleHyperlink>
</TextBlock>
<Button Content="&#xE115;"
FontFamily="Segoe MDL2 Assets"
Style="{StaticResource DefaultButtonStyle}"
FontSize="16"
Margin="-6,0,0,0"
AutomationProperties.Name="{x:Static p:Resources.Input_ShowAdvanced}"
ToolTip="{x:Static p:Resources.Input_ShowAdvanced}"
Background="Transparent"
Command="{Binding ShowAdvancedCommand}"
Visibility="{Binding ShowAdvancedSettings, Converter={StaticResource BoolValueConverter}}"
/>
<Button Grid.Column="1"
Height="23"
MinWidth="75"
Style="{StaticResource AccentButtonStyle}"
MinWidth="76"
Command="{Binding ResizeCommand}"
AutomationProperties.Name="{x:Static p:Resources.Resize_Tooltip}"
Content="{x:Static p:Resources.Input_Resize}"
IsDefault="True"/>
<Button Grid.Column="2"
Height="23"
MinWidth="75"
Margin="7,0,0,0"
Style="{StaticResource DefaultButtonStyle}"
MinWidth="76"
Margin="12,0,0,0"
Command="{Binding CancelCommand}"
Content="{x:Static p:Resources.Cancel}"
IsCancel="True"/>
</Grid>
</Border>
</StackPanel>
</UserControl>

View File

@ -1,6 +1,7 @@
<Window x:Class="ImageResizer.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="http://schemas.modernwpf.com/2019"
xmlns:behaviors="http://schemas.microsoft.com/xaml/behaviors"
xmlns:local="clr-namespace:ImageResizer.Views"
xmlns:p="clr-namespace:ImageResizer.Properties"
@ -11,7 +12,11 @@
ResizeMode="NoResize"
SizeToContent="WidthAndHeight"
Title="{x:Static p:Resources.ImageResizer}"
WindowStartupLocation="CenterScreen">
WindowStartupLocation="CenterScreen"
ui:WindowHelper.UseModernWindowStyle="True"
ui:TitleBar.IsIconVisible="True"
ui:TitleBar.Background="{DynamicResource PrimaryBackgroundBrush}"
AutomationProperties.Name="{x:Static p:Resources.ImageResizer}">
<Window.Resources>
<DataTemplate DataType="{x:Type vm:InputViewModel}">

View File

@ -4,6 +4,7 @@
xmlns:behaviors="http://schemas.microsoft.com/xaml/behaviors"
xmlns:local="clr-namespace:ImageResizer.Views"
xmlns:p="clr-namespace:ImageResizer.Properties"
Background="{DynamicResource PrimaryBackgroundBrush}"
MinWidth="350">
<UserControl.Resources>
@ -17,27 +18,29 @@
</behaviors:Interaction.Triggers>
<StackPanel>
<TextBlock Margin="11,11,11,0"
Style="{StaticResource MainInstructionTextBlockStyle}"
<TextBlock Margin="12,12,12,0"
FontSize="16"
Foreground="{DynamicResource PrimaryForegroundBrush}"
Text="{x:Static p:Resources.Progress_MainInstruction}"/>
<TextBlock Margin="11,11,11,0" Text="{Binding TimeRemaining,Converter={StaticResource TimeRemainingConverter}}"/>
<ProgressBar Height="15"
Margin="11,11,11,0"
<TextBlock Margin="12,12,12,0"
Foreground="{DynamicResource PrimaryForegroundBrush}"
Text="{Binding TimeRemaining,Converter={StaticResource TimeRemainingConverter}}"/>
<ProgressBar Height="16"
Margin="12,12,12,0"
Value="{Binding Progress}"
Maximum="1"/>
<Border Margin="0,11,0,0"
Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
BorderBrush="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}"
<Border Margin="0,12,0,0"
Background="{DynamicResource SecondaryBackgroundBrush}"
BorderBrush="{DynamicResource PrimaryBorderBrush}"
BorderThickness="0,1,0,0"
Padding="11,11">
Padding="12,12">
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<Button Height="23"
MinWidth="75"
<Button MinWidth="76"
Style="{StaticResource AccentButtonStyle}"
Command="{Binding StopCommand}"
Content="{x:Static p:Resources.Progress_Stop}"
IsCancel="True"/>
</StackPanel>
</Border>
</StackPanel>
</UserControl>

View File

@ -2,21 +2,23 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:p="clr-namespace:ImageResizer.Properties"
MinWidth="350">
MinWidth="350"
Background="{DynamicResource PrimaryBackgroundBrush}">
<StackPanel>
<TextBlock Margin="11,11,11,0"
Style="{StaticResource MainInstructionTextBlockStyle}"
<TextBlock Margin="12,12,12,0"
FontSize="16"
Foreground="{DynamicResource PrimaryForegroundBrush}"
Text="{x:Static p:Resources.Results_MainInstruction}"/>
<ScrollViewer MaxWidth="363"
MaxHeight="350"
HorizontalAlignment="Stretch"
VerticalScrollBarVisibility="Auto">
<ItemsControl Margin="11,4,11,0" ItemsSource="{Binding Errors}">
<ItemsControl Margin="12,4,12,0" ItemsSource="{Binding Errors}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="ResizeError">
<StackPanel>
<TextBlock Margin="0,7,0,0"
<TextBlock Margin="0,8,0,0"
FontWeight="Bold"
Text="{Binding File}"/>
<TextBlock Text="{Binding Error}" TextWrapping="Wrap"/>
@ -25,14 +27,13 @@
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<Border Margin="0,11,0,0"
Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
BorderBrush="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}"
<Border Margin="0,12,0,0"
Background="{DynamicResource SecondaryBackgroundBrush}"
BorderBrush="{DynamicResource PrimaryBorderBrush}"
BorderThickness="0,1,0,0"
Padding="11,11">
Padding="12,12">
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<Button Height="23"
MinWidth="75"
<Button MinWidth="76"
Command="{Binding CloseCommand}"
Content="{x:Static p:Resources.Results_Close}"
IsCancel="True"
@ -40,5 +41,4 @@
</StackPanel>
</Border>
</StackPanel>
</UserControl>