mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-06-07 17:42:45 +08:00
Color Picker V2 (#7710)
* Ground base for WPF version of V2 color picker
* Added theming support
* Layout fixes, added UWP listview styling
* Updated UI
* Added theming and Fluent to colorpicker. Styles cleanup
* Added animation for "color copied" message
* Added color format control, testing transparency
* Added roll-over behaviour, selectable textbox and right-click context menu
* Revert "Added roll-over behaviour, selectable textbox and right-click context menu"
This reverts commit af35a23532
.
* Delete context menu, mouse-over clipboard button and selectable text
* Implemented remove color command, set color editor topmost
* Missed some changes
* Added all currently supported color formats into editor, added support for future custom formats
* Added missed file
* Reverted WindowStyle = None
* Added drag and drop reorder behavior for color formats
* Removed custom close button, UI cleanup, added scrollviewer to colorformats
* Added close button
* Added color picker color control to configure current color
* Added possibility to add and remove color representations, commented out drag&drop reorder behavior
* Calculate color variations of the current color, on click adds a new color into the history
* Fixed reopening of editor, added rgb textboxes into color picker control, moved add color formats button at bottom
* Improved color schemes, similiar to Windows 10X
* Updated icon, window name and XAML cleanup
* Moved strings to Resources file
* Added Narrator support
* Accesibility stuff
* Revamped color picker color - now 3 sliders to configure color - hue, saturation, value, added bidirectional of setting values HEX/RGB/Sliders, validation of rgb and hex input
* UX improvements
* Removed color format management
* Removed colorformat hide context menu
* Improved colorpicker UI
* Added colorformats XAML to Settings
* Reverted runner change
* Margin fix
* Updated height of colorpicking tooltip
* Using dynamic width for color picker based on a content
* Fixed build
* Added H,S,V labels in front of gradient sliders in color picker control
* Color shades borders are now buttons, improved narrator support
* Added tabindexes
* Accesiblity improvements
* UI bugfix
* Fixed issue with occasional issue with saving color/removing colors due to locked settings file, decreased number of writes into settings.json, fixed throuttledActionInvoker to run only once, added rangeobservablecollection data type to be able to control notifications in observablecollection
* Updated installer with newly added libs
* Hide settings button since required functionality is not available yet
* Added comments to resource file
* Added reorder and enable/disable color formats from settings,
* Show message when colors history empty, open color editor in the center of screen
* Styling updates to now color selected popup
* Added horizontal gripper icon on pointerover
* Typo fix
* Added new color formats into editor
* Added 3 different activation actions to choose from
* Added new color formats into settings for editor
* Update src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw
Co-authored-by: htcfreek <61519853+htcfreek@users.noreply.github.com>
* Updated expect.txt
* Removed MahApps
* Removed MahApps from installer for Color Picker module
* Updated settings page
* Typo fix and moved string to Resources
* Typo fixes and string improvements
* Fixing build
* Replacing DispatcherTimer with Timer from System.Timers
* Fixing tests
* adjustments
* adjustments
* removed periods
* Fixing build
* unifiying language
* Added using statement in tests
* Disabled drop shadow for Color Picker and Zoom Window due to poor performance
* Stylecop fixes
Co-authored-by: Niels Laute <niels.laute@live.nl>
Co-authored-by: Niels Laute <niels9001@hotmail.com>
Co-authored-by: htcfreek <61519853+htcfreek@users.noreply.github.com>
Co-authored-by: Clint Rutkas <clint@rutkas.com>
This commit is contained in:
parent
eb1712808a
commit
a92fec2d0d
9
.github/actions/spell-check/expect.txt
vendored
9
.github/actions/spell-check/expect.txt
vendored
@ -27,6 +27,7 @@ Actionkeyword
|
||||
actionrunner
|
||||
activatable
|
||||
ACTIVATEAPP
|
||||
activationaction
|
||||
Addavirtualdesktop
|
||||
Addins
|
||||
ADDUNDORECORD
|
||||
@ -196,6 +197,7 @@ bsd
|
||||
bsearch
|
||||
BSODs
|
||||
bstr
|
||||
BText
|
||||
bti
|
||||
Btn
|
||||
btn
|
||||
@ -297,6 +299,8 @@ codereview
|
||||
COINIT
|
||||
Colorbrush
|
||||
colorconv
|
||||
colorhistory
|
||||
colorhistorylimit
|
||||
colorpicker
|
||||
colorpickerref
|
||||
COLORREF
|
||||
@ -510,6 +514,7 @@ DPopup
|
||||
DPSAPI
|
||||
Draggen
|
||||
DRAWFRAME
|
||||
drawingcolor
|
||||
dreamsofameaningfullife
|
||||
drivedetectionwarning
|
||||
DRM
|
||||
@ -827,6 +832,7 @@ gui
|
||||
guiddef
|
||||
GUITHREADINFO
|
||||
GValue
|
||||
GText
|
||||
GWL
|
||||
gwl
|
||||
GWLP
|
||||
@ -857,6 +863,7 @@ HDN
|
||||
hdrop
|
||||
HDS
|
||||
HEB
|
||||
helptext
|
||||
hglobal
|
||||
HGLOBAL
|
||||
hh
|
||||
@ -1889,6 +1896,7 @@ RStroked
|
||||
Rstrtmgr
|
||||
RTB
|
||||
Rtc
|
||||
RText
|
||||
rtf
|
||||
Rtl
|
||||
RTLREADING
|
||||
@ -2404,6 +2412,7 @@ VIRTUALDESKTOPCHANGE
|
||||
virtualization
|
||||
virtualized
|
||||
Virtualizing
|
||||
visiblecolorformats
|
||||
Visibletrue
|
||||
Visio
|
||||
visualbrush
|
||||
|
@ -598,7 +598,7 @@
|
||||
|
||||
<DirectoryRef Id="ColorPickerInstallFolder" FileSource="$(var.BinX64Dir)modules\$(var.ColorPickerProjectName)">
|
||||
<Component Id="Module_ColorPicker" Guid="8A52A69E-37B2-4BEA-9D73-77763066052F" Win64="yes">
|
||||
<?foreach File in ColorPicker.dll;System.IO.Abstractions.dll;ColorPicker.exe;ColorPicker.exe.config;Microsoft.Bcl.AsyncInterfaces.dll;Microsoft.Expression.Interactions.dll;Microsoft.PowerToys.Settings.UI.Lib.dll;PowerToysInterop.dll;System.Buffers.dll;System.Memory.dll;System.Numerics.Vectors.dll;System.Text.Encodings.Web.dll;System.Text.Json.dll;System.Threading.Tasks.Extensions.dll;System.ValueTuple.dll;System.Windows.Interactivity.dll;Telemetry.dll;ManagedCommon.dll;System.Runtime.CompilerServices.Unsafe.dll?>
|
||||
<?foreach File in ColorPicker.dll;System.IO.Abstractions.dll;ColorPicker.exe;ColorPicker.exe.config;Microsoft.Bcl.AsyncInterfaces.dll;Microsoft.Expression.Interactions.dll;Microsoft.PowerToys.Settings.UI.Lib.dll;PowerToysInterop.dll;System.Buffers.dll;System.Memory.dll;System.Numerics.Vectors.dll;System.Text.Encodings.Web.dll;System.Text.Json.dll;System.Threading.Tasks.Extensions.dll;System.ValueTuple.dll;System.Windows.Interactivity.dll;Telemetry.dll;ManagedCommon.dll;System.Runtime.CompilerServices.Unsafe.dll;ControlzEx.dll;Microsoft.Xaml.Behaviors.dll;ModernWpf.Controls.dll;ModernWpf.dll?>
|
||||
<File Id="ColorPickerFile_$(var.File)" Source="$(var.BinX64Dir)modules\$(var.ColorPickerProjectName)\$(var.File)" />
|
||||
<?endforeach?>
|
||||
</Component>
|
||||
|
@ -0,0 +1,72 @@
|
||||
// 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.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
{
|
||||
public class ColorFormatModel : INotifyPropertyChanged
|
||||
{
|
||||
private string _name;
|
||||
private string _example;
|
||||
private bool _isShown;
|
||||
|
||||
public ColorFormatModel(string name, string example, bool isShown)
|
||||
{
|
||||
Name = name;
|
||||
Example = example;
|
||||
IsShown = isShown;
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_name = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public string Example
|
||||
{
|
||||
get
|
||||
{
|
||||
return _example;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_example = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsShown
|
||||
{
|
||||
get
|
||||
{
|
||||
return _isShown;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_isShown = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
// 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 System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
|
||||
@ -14,6 +15,13 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
{
|
||||
ActivationShortcut = new HotkeySettings(true, false, false, true, 0x43);
|
||||
ChangeCursor = false;
|
||||
ColorHistory = new List<string>();
|
||||
ColorHistoryLimit = 20;
|
||||
VisibleColorFormats = new Dictionary<string, bool>();
|
||||
VisibleColorFormats.Add("HEX", true);
|
||||
VisibleColorFormats.Add("RGB", true);
|
||||
VisibleColorFormats.Add("HSL", true);
|
||||
ActivationAction = ColorPickerActivationAction.OpenColorPickerAndThenEditor;
|
||||
}
|
||||
|
||||
public HotkeySettings ActivationShortcut { get; set; }
|
||||
@ -25,6 +33,20 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
[JsonPropertyName("copiedcolorrepresentation")]
|
||||
public ColorRepresentationType CopiedColorRepresentation { get; set; }
|
||||
|
||||
[JsonPropertyName("activationaction")]
|
||||
public ColorPickerActivationAction ActivationAction { get; set; }
|
||||
|
||||
[JsonPropertyName("colorhistory")]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2227:Collection properties should be read only", Justification = "Need to change this collection")]
|
||||
public List<string> ColorHistory { get; set; }
|
||||
|
||||
[JsonPropertyName("colorhistorylimit")]
|
||||
public int ColorHistoryLimit { get; set; }
|
||||
|
||||
[JsonPropertyName("visiblecolorformats")]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2227:Collection properties should be read only", Justification = "Need to change this collection")]
|
||||
public Dictionary<string, bool> VisibleColorFormats { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
=> JsonSerializer.Serialize(this);
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
// 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.
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library.Enumerations
|
||||
{
|
||||
public enum ColorPickerActivationAction
|
||||
{
|
||||
// Activation shortcut opens editor
|
||||
OpenEditor,
|
||||
|
||||
// Activation shortcut opens color picker and after picking a color color is copied into clipboard and opens editor
|
||||
OpenColorPickerAndThenEditor,
|
||||
|
||||
// Activation shortcut opens color picker only and picking color copies color into clipboard
|
||||
OpenOnlyColorPicker,
|
||||
}
|
||||
}
|
@ -55,5 +55,4 @@
|
||||
<ProjectReference Include="..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||
<ProjectReference Include="..\..\common\ManagedTelemetry\Telemetry\Telemetry.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -4,21 +4,31 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Timers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||
{
|
||||
public class ColorPickerViewModel : Observable
|
||||
public class ColorPickerViewModel : Observable, IDisposable
|
||||
{
|
||||
private bool disposedValue;
|
||||
|
||||
// Delay saving of settings in order to avoid calling save multiple times and hitting file in use exception. If there is no other request to save settings in given interval, we proceed to save it, otherwise we schedule saving it after this interval
|
||||
private const int SaveSettingsDelayInMs = 500;
|
||||
|
||||
private GeneralSettings GeneralSettingsConfig { get; set; }
|
||||
|
||||
private readonly ISettingsUtils _settingsUtils;
|
||||
private readonly object _delayedActionLock = new object();
|
||||
|
||||
private readonly ColorPickerSettings _colorPickerSettings;
|
||||
private Timer _delayedTimer;
|
||||
|
||||
private bool _isEnabled;
|
||||
|
||||
@ -61,6 +71,13 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||
|
||||
// set the callback functions value to hangle outgoing IPC message.
|
||||
SendConfigMSG = ipcMSGCallBackFunc;
|
||||
|
||||
_delayedTimer = new Timer();
|
||||
_delayedTimer.Interval = SaveSettingsDelayInMs;
|
||||
_delayedTimer.Elapsed += DelayedTimer_Tick;
|
||||
_delayedTimer.AutoReset = false;
|
||||
|
||||
InitializeColorFormats();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -129,6 +146,139 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public bool ActivationOpensEditor
|
||||
{
|
||||
get => _colorPickerSettings.Properties.ActivationAction == ColorPickerActivationAction.OpenEditor;
|
||||
set
|
||||
{
|
||||
if (value && _colorPickerSettings.Properties.ActivationAction != ColorPickerActivationAction.OpenEditor)
|
||||
{
|
||||
_colorPickerSettings.Properties.ActivationAction = ColorPickerActivationAction.OpenEditor;
|
||||
OnPropertyChanged(nameof(ActivationOpensEditor));
|
||||
NotifySettingsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool ActivationOpensColorPickerOnly
|
||||
{
|
||||
get => _colorPickerSettings.Properties.ActivationAction == ColorPickerActivationAction.OpenOnlyColorPicker;
|
||||
set
|
||||
{
|
||||
if (value && _colorPickerSettings.Properties.ActivationAction != ColorPickerActivationAction.OpenOnlyColorPicker)
|
||||
{
|
||||
_colorPickerSettings.Properties.ActivationAction = ColorPickerActivationAction.OpenOnlyColorPicker;
|
||||
OnPropertyChanged(nameof(ActivationOpensColorPickerOnly));
|
||||
NotifySettingsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool ActivationOpensColorPickerAndEditor
|
||||
{
|
||||
get => _colorPickerSettings.Properties.ActivationAction == ColorPickerActivationAction.OpenColorPickerAndThenEditor;
|
||||
set
|
||||
{
|
||||
if (value && _colorPickerSettings.Properties.ActivationAction != ColorPickerActivationAction.OpenColorPickerAndThenEditor)
|
||||
{
|
||||
_colorPickerSettings.Properties.ActivationAction = ColorPickerActivationAction.OpenColorPickerAndThenEditor;
|
||||
OnPropertyChanged(nameof(ActivationOpensEditor));
|
||||
NotifySettingsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<ColorFormatModel> ColorFormats { get; } = new ObservableCollection<ColorFormatModel>();
|
||||
|
||||
private void InitializeColorFormats()
|
||||
{
|
||||
var visibleFormats = _colorPickerSettings.Properties.VisibleColorFormats;
|
||||
var formatsUnordered = new List<ColorFormatModel>();
|
||||
|
||||
var hexFormatName = ColorRepresentationType.HEX.ToString();
|
||||
var rgbFormatName = ColorRepresentationType.RGB.ToString();
|
||||
var hslFormatName = ColorRepresentationType.HSL.ToString();
|
||||
var hsvFormatName = ColorRepresentationType.HSV.ToString();
|
||||
var cmykFormatName = ColorRepresentationType.CMYK.ToString();
|
||||
var hsbFormatName = ColorRepresentationType.HSB.ToString();
|
||||
var hsiFormatName = ColorRepresentationType.HSI.ToString();
|
||||
var hwbFormatName = ColorRepresentationType.HWB.ToString();
|
||||
var ncolFormatName = ColorRepresentationType.NCol.ToString();
|
||||
|
||||
formatsUnordered.Add(new ColorFormatModel(hexFormatName, "#EF68FF", visibleFormats.ContainsKey(hexFormatName) && visibleFormats[hexFormatName]));
|
||||
formatsUnordered.Add(new ColorFormatModel(rgbFormatName, "rgb(239, 104, 255)", visibleFormats.ContainsKey(rgbFormatName) && visibleFormats[rgbFormatName]));
|
||||
formatsUnordered.Add(new ColorFormatModel(hslFormatName, "hsl(294, 100%, 70%)", visibleFormats.ContainsKey(hslFormatName) && visibleFormats[hslFormatName]));
|
||||
formatsUnordered.Add(new ColorFormatModel(hsvFormatName, "hsv(294, 59%, 100%)", visibleFormats.ContainsKey(hsvFormatName) && visibleFormats[hsvFormatName]));
|
||||
formatsUnordered.Add(new ColorFormatModel(cmykFormatName, "cmyk(6%, 59%, 0%, 0%)", visibleFormats.ContainsKey(cmykFormatName) && visibleFormats[cmykFormatName]));
|
||||
formatsUnordered.Add(new ColorFormatModel(hsbFormatName, "hsb(100, 50%, 75%)", visibleFormats.ContainsKey(hsbFormatName) && visibleFormats[hsbFormatName]));
|
||||
formatsUnordered.Add(new ColorFormatModel(hsiFormatName, "hsi(100, 50%, 75%)", visibleFormats.ContainsKey(hsiFormatName) && visibleFormats[hsiFormatName]));
|
||||
formatsUnordered.Add(new ColorFormatModel(hwbFormatName, "hwb(100, 50%, 75%)", visibleFormats.ContainsKey(hwbFormatName) && visibleFormats[hwbFormatName]));
|
||||
formatsUnordered.Add(new ColorFormatModel(ncolFormatName, "R10, 50%, 75%", visibleFormats.ContainsKey(ncolFormatName) && visibleFormats[ncolFormatName]));
|
||||
|
||||
foreach (var storedColorFormat in _colorPickerSettings.Properties.VisibleColorFormats)
|
||||
{
|
||||
var predefinedFormat = formatsUnordered.FirstOrDefault(it => it.Name == storedColorFormat.Key);
|
||||
if (predefinedFormat != null)
|
||||
{
|
||||
predefinedFormat.PropertyChanged += ColorFormat_PropertyChanged;
|
||||
ColorFormats.Add(predefinedFormat);
|
||||
formatsUnordered.Remove(predefinedFormat);
|
||||
}
|
||||
}
|
||||
|
||||
// settings file might not have all formats listed, add remaining ones we support
|
||||
foreach (var remainingColorFormat in formatsUnordered)
|
||||
{
|
||||
remainingColorFormat.PropertyChanged += ColorFormat_PropertyChanged;
|
||||
ColorFormats.Add(remainingColorFormat);
|
||||
}
|
||||
|
||||
ColorFormats.CollectionChanged += ColorFormats_CollectionChanged;
|
||||
}
|
||||
|
||||
private void ColorFormats_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
UpdateColorFormats();
|
||||
ScheduleSavingOfSettings();
|
||||
}
|
||||
|
||||
private void ColorFormat_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
UpdateColorFormats();
|
||||
ScheduleSavingOfSettings();
|
||||
}
|
||||
|
||||
private void ScheduleSavingOfSettings()
|
||||
{
|
||||
lock (_delayedActionLock)
|
||||
{
|
||||
if (_delayedTimer.Enabled)
|
||||
{
|
||||
_delayedTimer.Stop();
|
||||
}
|
||||
|
||||
_delayedTimer.Start();
|
||||
}
|
||||
}
|
||||
|
||||
private void DelayedTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
lock (_delayedActionLock)
|
||||
{
|
||||
_delayedTimer.Stop();
|
||||
NotifySettingsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateColorFormats()
|
||||
{
|
||||
_colorPickerSettings.Properties.VisibleColorFormats.Clear();
|
||||
foreach (var colorFormat in ColorFormats)
|
||||
{
|
||||
_colorPickerSettings.Properties.VisibleColorFormats.Add(colorFormat.Name, colorFormat.IsShown);
|
||||
}
|
||||
}
|
||||
|
||||
private void NotifySettingsChanged()
|
||||
{
|
||||
// Using InvariantCulture as this is an IPC message
|
||||
@ -139,5 +289,24 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||
ColorPickerSettings.ModuleName,
|
||||
JsonSerializer.Serialize(_colorPickerSettings)));
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_delayedTimer.Dispose();
|
||||
}
|
||||
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,27 +39,29 @@ namespace ViewModelTests
|
||||
|
||||
// Act
|
||||
// Initialise View Model with test Config files
|
||||
ColorPickerViewModel viewModel = new ColorPickerViewModel(mockSettingsUtils, generalSettingsRepository, ColorPickerIsEnabledByDefaultIPC);
|
||||
using (var viewModel = new ColorPickerViewModel(mockSettingsUtils, generalSettingsRepository, ColorPickerIsEnabledByDefaultIPC))
|
||||
{
|
||||
// Assert
|
||||
// Verify that the old settings persisted
|
||||
Assert.AreEqual(originalGeneralSettings.Enabled.ColorPicker, viewModel.IsEnabled);
|
||||
Assert.AreEqual(originalSettings.Properties.ActivationShortcut.ToString(), viewModel.ActivationShortcut.ToString());
|
||||
Assert.AreEqual(originalSettings.Properties.ChangeCursor, viewModel.ChangeCursor);
|
||||
|
||||
// Assert
|
||||
// Verify that the old settings persisted
|
||||
Assert.AreEqual(originalGeneralSettings.Enabled.ColorPicker, viewModel.IsEnabled);
|
||||
Assert.AreEqual(originalSettings.Properties.ActivationShortcut.ToString(), viewModel.ActivationShortcut.ToString());
|
||||
Assert.AreEqual(originalSettings.Properties.ChangeCursor, viewModel.ChangeCursor);
|
||||
|
||||
// Verify that the stub file was used
|
||||
var expectedCallCount = 2; // once via the view model, and once by the test (GetSettings<T>)
|
||||
BackCompatTestProperties.VerifyModuleIOProviderWasRead(mockIOProvider, ColorPickerSettings.ModuleName, expectedCallCount);
|
||||
BackCompatTestProperties.VerifyGeneralSettingsIOProviderWasRead(mockGeneralIOProvider, expectedCallCount);
|
||||
// Verify that the stub file was used
|
||||
var expectedCallCount = 2; // once via the view model, and once by the test (GetSettings<T>)
|
||||
BackCompatTestProperties.VerifyModuleIOProviderWasRead(mockIOProvider, ColorPickerSettings.ModuleName, expectedCallCount);
|
||||
BackCompatTestProperties.VerifyGeneralSettingsIOProviderWasRead(mockGeneralIOProvider, expectedCallCount);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ColorPickerIsEnabledByDefault()
|
||||
{
|
||||
var mockSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils<ColorPickerSettings>();
|
||||
var viewModel = new ColorPickerViewModel(ISettingsUtilsMocks.GetStubSettingsUtils<ColorPickerSettings>().Object, SettingsRepository<GeneralSettings>.GetInstance(ISettingsUtilsMocks.GetStubSettingsUtils<GeneralSettings>().Object), ColorPickerIsEnabledByDefaultIPC);
|
||||
|
||||
Assert.IsTrue(viewModel.IsEnabled);
|
||||
using (var viewModel = new ColorPickerViewModel(ISettingsUtilsMocks.GetStubSettingsUtils<ColorPickerSettings>().Object, SettingsRepository<GeneralSettings>.GetInstance(ISettingsUtilsMocks.GetStubSettingsUtils<GeneralSettings>().Object), ColorPickerIsEnabledByDefaultIPC))
|
||||
{
|
||||
Assert.IsTrue(viewModel.IsEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
private static int ColorPickerIsEnabledByDefaultIPC(string msg)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:Custom="using:Microsoft.PowerToys.Settings.UI.Controls"
|
||||
xmlns:Color="using:Microsoft.PowerToys.Settings.UI.Library.ViewModels" xmlns:Interactivity="using:Microsoft.Xaml.Interactivity" xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="300"
|
||||
d:DesignWidth="400"
|
||||
@ -13,95 +14,6 @@
|
||||
AutomationProperties.LandmarkType="Main">
|
||||
|
||||
<Grid RowSpacing="{StaticResource DefaultRowSpacing}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel x:Name="ColorPickerView" Orientation="Vertical">
|
||||
<ToggleSwitch x:Uid="ColorPicker_EnableColorPicker" IsOn="{Binding IsEnabled, Mode=TwoWay}" />
|
||||
|
||||
<Custom:HotkeySettingsControl x:Uid="ColorPicker_ActivationShortcut"
|
||||
MinWidth="240"
|
||||
Margin="{StaticResource MediumTopMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
Enabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}"
|
||||
HotkeySettings="{x:Bind Path=ViewModel.ActivationShortcut, Mode=TwoWay}"
|
||||
Keys="Win, Ctrl, Alt, Shift" />
|
||||
|
||||
<TextBlock x:Uid="ShortcutGuide_Appearance_Behavior"
|
||||
Foreground="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled, Converter={StaticResource ModuleEnabledToForegroundConverter}}"
|
||||
Style="{StaticResource SettingsGroupTitleStyle}" />
|
||||
|
||||
<ComboBox x:Name="ColorPicker_ComboBox"
|
||||
x:Uid="ColorPicker_CopiedColorRepresentation"
|
||||
MinWidth="240"
|
||||
Margin="{StaticResource SmallTopMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
DisplayMemberPath="Value"
|
||||
IsEnabled="{Binding IsEnabled}"
|
||||
ItemsSource="{Binding SelectableColorRepresentations}"
|
||||
Loaded="ColorPicker_ComboBox_Loaded"
|
||||
SelectedValue="{Binding SelectedColorRepresentationValue, Mode=TwoWay}"
|
||||
SelectedValuePath="Key" />
|
||||
|
||||
<!--
|
||||
Disabling this until we have a safer way to reset cursor as
|
||||
we can hit a state where the cursor doesn't reset
|
||||
|
||||
<CheckBox x:Uid="ColorPicker_ChangeCursor"
|
||||
IsChecked="{Binding ChangeCursor, Mode=TwoWay}"
|
||||
Margin="{StaticResource SmallTopMargin}"
|
||||
IsEnabled="{Binding IsEnabled}"/>
|
||||
-->
|
||||
</StackPanel>
|
||||
|
||||
<RelativePanel x:Name="SidePanel"
|
||||
Grid.Column="1"
|
||||
Width="{StaticResource SidePanelWidth}"
|
||||
HorizontalAlignment="Left">
|
||||
<StackPanel x:Name="DescriptionPanel">
|
||||
<TextBlock x:Name="AboutTitle"
|
||||
x:Uid="About_ColorPicker"
|
||||
Grid.ColumnSpan="2"
|
||||
Margin="{StaticResource XSmallBottomMargin}"
|
||||
Style="{StaticResource SettingsGroupTitleStyle}" />
|
||||
<TextBlock x:Uid="ColorPicker_Description"
|
||||
Grid.Row="1"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
|
||||
<Border x:Name="AboutImage"
|
||||
Grid.Row="2"
|
||||
MaxWidth="240"
|
||||
Margin="{StaticResource SmallTopBottomMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
CornerRadius="4"
|
||||
RelativePanel.Below="DescriptionPanel">
|
||||
<Image x:Uid="ColorPicker_Image" Source="ms-appx:///Assets/Modules/ColorPicker.png" />
|
||||
</Border>
|
||||
<StackPanel x:Name="LinksPanel"
|
||||
Margin="0,1,0,0"
|
||||
Orientation="Vertical"
|
||||
RelativePanel.Below="AboutImage">
|
||||
<HyperlinkButton NavigateUri="https://aka.ms/PowerToysOverview_ColorPicker">
|
||||
<TextBlock x:Uid="Module_overview" />
|
||||
</HyperlinkButton>
|
||||
<HyperlinkButton NavigateUri="https://aka.ms/powerToysGiveFeedback">
|
||||
<TextBlock x:Uid="Give_Feedback" />
|
||||
</HyperlinkButton>
|
||||
|
||||
<TextBlock x:Uid="AttributionTitle" Style="{StaticResource SettingsGroupTitleStyle}" />
|
||||
|
||||
<HyperlinkButton Margin="0,-3,0,0" NavigateUri="https://github.com/martinchrzan/ColorPicker/">
|
||||
<TextBlock Text="Martin Chrzan's Color Picker" TextWrapping="Wrap" />
|
||||
</HyperlinkButton>
|
||||
</StackPanel>
|
||||
</RelativePanel>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="LayoutVisualStates">
|
||||
<VisualState x:Name="WideLayout">
|
||||
@ -126,5 +38,201 @@
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel Orientation="Vertical" x:Name="ColorPickerView">
|
||||
<ToggleSwitch x:Uid="ColorPicker_EnableColorPicker"
|
||||
IsOn="{Binding IsEnabled, Mode=TwoWay}"/>
|
||||
|
||||
<TextBlock x:Uid="Shortcuts"
|
||||
Style="{StaticResource SettingsGroupTitleStyle}"
|
||||
Foreground="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled, Converter={StaticResource ModuleEnabledToForegroundConverter}}"/>
|
||||
|
||||
<Custom:HotkeySettingsControl x:Uid="ColorPicker_ActivationShortcut"
|
||||
Margin="{StaticResource SmallTopMargin}"
|
||||
HotkeySettings="{x:Bind Path=ViewModel.ActivationShortcut, Mode=TwoWay}"
|
||||
Keys="Win, Ctrl, Alt, Shift"
|
||||
Enabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}"
|
||||
HorizontalAlignment="Left"
|
||||
MinWidth="240"
|
||||
/>
|
||||
|
||||
<TextBlock x:Uid="ColorPicker_ActivationAction"
|
||||
Margin="{StaticResource MediumTopMargin}"
|
||||
x:Name="ColorPicker_ActivationAction"
|
||||
Foreground="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled, Converter={StaticResource ModuleEnabledToForegroundConverter}}"/>
|
||||
<StackPanel AutomationProperties.LabeledBy="{Binding ElementName=ColorPicker_ActivationAction}" Margin="0,-4,0,0">
|
||||
<RadioButton
|
||||
IsChecked="{Binding ActivationOpensColorPickerAndEditor, Mode=TwoWay}"
|
||||
Margin="{StaticResource SmallTopMargin}"
|
||||
IsEnabled="{Binding IsEnabled}"
|
||||
GroupName="ColorPickerActivationAction">
|
||||
<RadioButton.Content>
|
||||
<TextBlock TextWrapping="WrapWholeWords" LineHeight="20">
|
||||
<Run x:Uid="ColorPickerFirst"/>
|
||||
<LineBreak/>
|
||||
<Run Foreground="{ThemeResource SystemBaseMediumColor}"
|
||||
x:Uid="ColorPickerFirst_Description"/>
|
||||
</TextBlock>
|
||||
</RadioButton.Content>
|
||||
</RadioButton>
|
||||
|
||||
<RadioButton IsChecked="{Binding ActivationOpensEditor, Mode=TwoWay}"
|
||||
Margin="{StaticResource SmallTopMargin}"
|
||||
IsEnabled="{Binding IsEnabled}"
|
||||
GroupName="ColorPickerActivationAction">
|
||||
<RadioButton.Content>
|
||||
<TextBlock TextWrapping="WrapWholeWords" LineHeight="20">
|
||||
<Run x:Uid="EditorFirst"/>
|
||||
<LineBreak/>
|
||||
<Run Foreground="{ThemeResource SystemBaseMediumColor}" x:Uid="EditorFirst_Description"/>
|
||||
</TextBlock>
|
||||
</RadioButton.Content>
|
||||
</RadioButton>
|
||||
|
||||
<RadioButton IsChecked="{Binding ActivationOpensColorPickerOnly, Mode=TwoWay}"
|
||||
Margin="{StaticResource SmallTopMargin}"
|
||||
IsEnabled="{Binding IsEnabled}"
|
||||
GroupName="ColorPickerActivationAction">
|
||||
<RadioButton.Content>
|
||||
<TextBlock TextWrapping="WrapWholeWords" LineHeight="20">
|
||||
<Run x:Uid="ColorPickerOnly"/>
|
||||
<LineBreak/>
|
||||
<Run x:Uid="ColorPickerOnly_Description" Foreground="{ThemeResource SystemBaseMediumColor}"/>
|
||||
</TextBlock>
|
||||
</RadioButton.Content>
|
||||
</RadioButton>
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock x:Uid="ColorFormats"
|
||||
Style="{StaticResource SettingsGroupTitleStyle}"
|
||||
Foreground="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled, Converter={StaticResource ModuleEnabledToForegroundConverter}}"/>
|
||||
|
||||
<ComboBox x:Name="ColorPicker_ComboBox"
|
||||
x:Uid="ColorPicker_CopiedColorRepresentation"
|
||||
MinWidth="240"
|
||||
Margin="{StaticResource SmallTopMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
DisplayMemberPath="Value"
|
||||
IsEnabled="{Binding IsEnabled}"
|
||||
ItemsSource="{Binding SelectableColorRepresentations}"
|
||||
Loaded="ColorPicker_ComboBox_Loaded"
|
||||
SelectedValue="{Binding SelectedColorRepresentationValue, Mode=TwoWay}"
|
||||
SelectedValuePath="Key" />
|
||||
|
||||
<TextBlock Margin="{StaticResource MediumTopMargin}"
|
||||
x:Name="ColorFormatsListViewLabel"
|
||||
TextWrapping="WrapWholeWords"
|
||||
x:Uid="ColorPicker_ColorFormatsDescription"/>
|
||||
<ListView ItemsSource="{Binding ColorFormats, Mode=TwoWay}"
|
||||
AllowDrop="True"
|
||||
MaxWidth="466"
|
||||
AutomationProperties.LabeledBy="{Binding ElementName=ColorFormatsListViewLabel}"
|
||||
CanReorderItems="True"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="-12,6,0,0">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Width="466" Background="Transparent">
|
||||
<Interactivity:Interaction.Behaviors>
|
||||
<Core:EventTriggerBehavior EventName="PointerEntered">
|
||||
<Core:ChangePropertyAction TargetObject="{Binding ElementName=GripperIcon}" PropertyName="Visibility" Value="Visible" />
|
||||
</Core:EventTriggerBehavior>
|
||||
<Core:EventTriggerBehavior EventName="PointerExited">
|
||||
<Core:ChangePropertyAction TargetObject="{Binding ElementName=GripperIcon}" PropertyName="Visibility" Value="Collapsed" />
|
||||
</Core:EventTriggerBehavior>
|
||||
</Interactivity:Interaction.Behaviors>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock FontWeight="SemiBold"
|
||||
FontSize="16"
|
||||
Margin="0,8,0,0"
|
||||
Text="{Binding Name}"/>
|
||||
<TextBlock Foreground="{ThemeResource SystemAccentColor}"
|
||||
Text="{Binding Example}"
|
||||
Grid.Row="1"
|
||||
Margin="0,0,0,8"/>
|
||||
<ToggleSwitch IsOn="{Binding IsShown, Mode=TwoWay}"
|
||||
Grid.RowSpan="2"
|
||||
HorizontalAlignment="Right" />
|
||||
<TextBlock Text=""
|
||||
Visibility="Collapsed"
|
||||
x:Name="GripperIcon"
|
||||
VerticalAlignment="Center"
|
||||
Grid.RowSpan="2"
|
||||
FontSize="16"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="0,0,36,0"
|
||||
FontFamily="Segoe MDL2 Assets" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
|
||||
<!--
|
||||
Disabling this until we have a safer way to reset cursor as
|
||||
we can hit a state where the cursor doesn't reset
|
||||
|
||||
<CheckBox x:Uid="ColorPicker_ChangeCursor"
|
||||
IsChecked="{Binding ChangeCursor, Mode=TwoWay}"
|
||||
Margin="{StaticResource SmallTopMargin}"
|
||||
IsEnabled="{Binding IsEnabled}"/>
|
||||
-->
|
||||
</StackPanel>
|
||||
|
||||
<RelativePanel x:Name="SidePanel"
|
||||
HorizontalAlignment="Left"
|
||||
Width="{StaticResource SidePanelWidth}"
|
||||
Grid.Column="1">
|
||||
<StackPanel x:Name="DescriptionPanel">
|
||||
<TextBlock x:Uid="About_ColorPicker"
|
||||
x:Name="AboutTitle"
|
||||
Grid.ColumnSpan="2"
|
||||
Style="{StaticResource SettingsGroupTitleStyle}"
|
||||
Margin="{StaticResource XSmallBottomMargin}"/>
|
||||
<TextBlock x:Uid="ColorPicker_Description"
|
||||
TextWrapping="Wrap"
|
||||
Grid.Row="1" />
|
||||
</StackPanel>
|
||||
|
||||
<Border x:Name="AboutImage"
|
||||
CornerRadius="4"
|
||||
Grid.Row="2"
|
||||
MaxWidth="240"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="{StaticResource SmallTopBottomMargin}"
|
||||
RelativePanel.Below="DescriptionPanel">
|
||||
<Image x:Uid="ColorPicker_Image" Source="ms-appx:///Assets/Modules/ColorPicker.png" />
|
||||
</Border>
|
||||
<StackPanel x:Name="LinksPanel"
|
||||
Margin="0,1,0,0"
|
||||
RelativePanel.Below="AboutImage"
|
||||
Orientation="Vertical" >
|
||||
<HyperlinkButton NavigateUri="https://aka.ms/PowerToysOverview_ColorPicker">
|
||||
<TextBlock x:Uid="Module_overview" />
|
||||
</HyperlinkButton>
|
||||
<HyperlinkButton NavigateUri="https://aka.ms/powerToysGiveFeedback">
|
||||
<TextBlock x:Uid="Give_Feedback" />
|
||||
</HyperlinkButton>
|
||||
|
||||
<TextBlock
|
||||
x:Uid="AttributionTitle"
|
||||
Style="{StaticResource SettingsGroupTitleStyle}" />
|
||||
|
||||
<HyperlinkButton Margin="0,-3,0,0"
|
||||
NavigateUri="https://github.com/martinchrzan/ColorPicker/">
|
||||
<TextBlock Text="Martin Chrzan's Color Picker" TextWrapping="Wrap" />
|
||||
</HyperlinkButton>
|
||||
</StackPanel>
|
||||
</RelativePanel>
|
||||
</Grid>
|
||||
</Page>
|
@ -4,7 +4,6 @@
|
||||
|
||||
using System.IO.Abstractions;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.ViewModels;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
|
@ -50,7 +50,7 @@
|
||||
<ToggleSwitch x:Uid="PowerLauncher_EnablePowerLauncher"
|
||||
IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.EnablePowerLauncher}"/>
|
||||
|
||||
<TextBlock x:Uid="PowerLauncher_Shortcuts"
|
||||
<TextBlock x:Uid="Shortcuts"
|
||||
Style="{StaticResource SettingsGroupTitleStyle}"
|
||||
Foreground="{x:Bind Mode=OneWay, Path=ViewModel.EnablePowerLauncher, Converter={StaticResource ModuleEnabledToForegroundConverter}}"/>
|
||||
|
||||
|
@ -2,10 +2,13 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:ColorPickerUI"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ui:ThemeResources />
|
||||
<ui:XamlControlsResources />
|
||||
<ResourceDictionary Source="Resources/Styles.xaml"/>
|
||||
<ResourceDictionary Source="Resources/ViewModelViewMappings.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
@ -5,6 +5,7 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using ColorPicker;
|
||||
using ColorPicker.Helpers;
|
||||
using ColorPicker.Mouse;
|
||||
using ManagedCommon;
|
||||
@ -20,6 +21,7 @@ namespace ColorPickerUI
|
||||
private static string[] _args;
|
||||
private int _powerToysPid;
|
||||
private bool disposedValue;
|
||||
private ThemeManager _themeManager;
|
||||
|
||||
[STAThread]
|
||||
public static void Main(string[] args)
|
||||
@ -64,6 +66,7 @@ namespace ColorPickerUI
|
||||
Environment.Exit(0);
|
||||
});
|
||||
|
||||
_themeManager = new ThemeManager(this);
|
||||
base.OnStartup(e);
|
||||
}
|
||||
|
||||
@ -93,6 +96,8 @@ namespace ColorPickerUI
|
||||
_instanceMutex?.Dispose();
|
||||
}
|
||||
|
||||
_themeManager?.Dispose();
|
||||
|
||||
// TODO: free unmanaged resources (unmanaged objects) and override finalizer
|
||||
// TODO: set large fields to null
|
||||
disposedValue = true;
|
||||
|
@ -6,7 +6,6 @@ using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Interactivity;
|
||||
using System.Windows.Media.Animation;
|
||||
using ColorPicker.Constants;
|
||||
|
||||
namespace ColorPicker.Behaviors
|
||||
{
|
||||
@ -42,16 +41,10 @@ namespace ColorPicker.Behaviors
|
||||
|
||||
var opacityAppear = new DoubleAnimation(0d, 1d, duration)
|
||||
{
|
||||
EasingFunction = new QuadraticEase() { EasingMode = EasingMode.EaseOut },
|
||||
};
|
||||
|
||||
var resize = new DoubleAnimation(0d, WindowConstant.PickerWindowWidth, duration)
|
||||
{
|
||||
EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseOut },
|
||||
EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseInOut },
|
||||
};
|
||||
|
||||
AssociatedObject.BeginAnimation(UIElement.OpacityProperty, opacityAppear);
|
||||
AssociatedObject.BeginAnimation(FrameworkElement.WidthProperty, resize);
|
||||
}
|
||||
|
||||
private void Hide()
|
||||
@ -59,10 +52,8 @@ namespace ColorPicker.Behaviors
|
||||
var duration = new Duration(TimeSpan.FromMilliseconds(1));
|
||||
|
||||
var opacityAppear = new DoubleAnimation(0d, duration);
|
||||
var resize = new DoubleAnimation(0d, duration);
|
||||
|
||||
AssociatedObject.BeginAnimation(UIElement.OpacityProperty, opacityAppear);
|
||||
AssociatedObject.BeginAnimation(FrameworkElement.WidthProperty, resize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,69 @@
|
||||
// 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.Collections.ObjectModel;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interactivity;
|
||||
using ColorPicker.Models;
|
||||
|
||||
namespace ColorPicker.Behaviors
|
||||
{
|
||||
public class DragAndDropReorderBehavior : Behavior<ItemsControl>
|
||||
{
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
||||
var style = new Style(typeof(ContentPresenter));
|
||||
style.Setters.Add(
|
||||
new EventSetter(
|
||||
FrameworkElement.PreviewMouseMoveEvent,
|
||||
new MouseEventHandler(ItemPreviewMouseMove)));
|
||||
style.Setters.Add(
|
||||
new EventSetter(
|
||||
FrameworkElement.DropEvent,
|
||||
new DragEventHandler(ItemDrop)));
|
||||
AssociatedObject.ItemContainerStyle = style;
|
||||
}
|
||||
|
||||
private void ItemPreviewMouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
Task.Run(
|
||||
new Action(() =>
|
||||
{
|
||||
Dispatcher.BeginInvoke(
|
||||
new Action(() =>
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
var data = new DataObject();
|
||||
data.SetData("Source", (sender as FrameworkElement).DataContext);
|
||||
DragDrop.DoDragDrop(sender as DependencyObject, data, DragDropEffects.Move);
|
||||
e.Handled = true;
|
||||
}
|
||||
}), null);
|
||||
}), CancellationToken.None);
|
||||
}
|
||||
}
|
||||
|
||||
private void ItemDrop(object sender, DragEventArgs e)
|
||||
{
|
||||
var source = e.Data.GetData("Source") as ColorFormatModel;
|
||||
if (source != null)
|
||||
{
|
||||
int newIndex = AssociatedObject.Items.IndexOf((sender as FrameworkElement).DataContext);
|
||||
var list = AssociatedObject.ItemsSource as ObservableCollection<ColorFormatModel>;
|
||||
list.RemoveAt(list.IndexOf(source));
|
||||
list.Insert(newIndex, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
// 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.Windows;
|
||||
using System.Windows.Interactivity;
|
||||
|
||||
namespace ColorPicker.Behaviors
|
||||
{
|
||||
public class DragWindowBehavior : Behavior<FrameworkElement>
|
||||
{
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
AssociatedObject.Loaded += AssociatedObject_Loaded;
|
||||
}
|
||||
|
||||
private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AssociatedObject.MouseLeftButtonDown += AssociatedObject_MouseLeftButtonDown;
|
||||
}
|
||||
|
||||
private void AssociatedObject_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
var parentWindow = Window.GetWindow(AssociatedObject);
|
||||
if (parentWindow != null)
|
||||
{
|
||||
parentWindow.DragMove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ namespace ColorPicker.Behaviors
|
||||
{
|
||||
var sender = ((MoveWindowBehavior)d).AssociatedObject;
|
||||
var move = new DoubleAnimation(sender.Left, (double)e.NewValue, new Duration(TimeSpan.FromMilliseconds(150)), FillBehavior.Stop);
|
||||
move.EasingFunction = new QuadraticEase() { EasingMode = EasingMode.EaseOut };
|
||||
move.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseInOut };
|
||||
sender.BeginAnimation(Window.LeftProperty, move, HandoffBehavior.Compose);
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ namespace ColorPicker.Behaviors
|
||||
{
|
||||
var sender = ((MoveWindowBehavior)d).AssociatedObject;
|
||||
var move = new DoubleAnimation(sender.Top, (double)e.NewValue, new Duration(TimeSpan.FromMilliseconds(150)), FillBehavior.Stop);
|
||||
move.EasingFunction = new QuadraticEase() { EasingMode = EasingMode.EaseOut };
|
||||
move.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseInOut };
|
||||
sender.BeginAnimation(Window.TopProperty, move, HandoffBehavior.Compose);
|
||||
}
|
||||
|
||||
|
27
src/modules/colorPicker/ColorPickerUI/ColorEditorWindow.xaml
Normal file
27
src/modules/colorPicker/ColorPickerUI/ColorEditorWindow.xaml
Normal file
@ -0,0 +1,27 @@
|
||||
<Window x:Class="ColorPicker.ColorEditorWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
xmlns:p="clr-namespace:ColorPicker.Properties"
|
||||
mc:Ignorable="d"
|
||||
AutomationProperties.Name="{x:Static p:Resources.cp_editor}"
|
||||
xmlns:e="http://schemas.microsoft.com/expression/2010/interactivity"
|
||||
xmlns:behaviors="clr-namespace:ColorPicker.Behaviors"
|
||||
ui:TitleBar.ExtendViewIntoTitleBar="True"
|
||||
ui:TitleBar.ButtonStyle="{DynamicResource AppTitleBarButtonStyle}"
|
||||
ui:WindowHelper.UseModernWindowStyle="True"
|
||||
BorderBrush="{DynamicResource WindowBorderBrush}"
|
||||
Background="{DynamicResource PrimaryBackgroundBrush}"
|
||||
BorderThickness="1"
|
||||
Title="Color Picker"
|
||||
Height="380"
|
||||
Width="400"
|
||||
ResizeMode="NoResize"
|
||||
Topmost="True"
|
||||
WindowStartupLocation="CenterScreen">
|
||||
<e:Interaction.Behaviors>
|
||||
<behaviors:CloseZoomWindowBehavior/>
|
||||
</e:Interaction.Behaviors>
|
||||
</Window>
|
@ -0,0 +1,38 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace ColorPicker
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ColorEditorWindow.xaml
|
||||
/// </summary>
|
||||
public partial class ColorEditorWindow : Window
|
||||
{
|
||||
public ColorEditorWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
Closing += ColorEditorWindow_Closing;
|
||||
}
|
||||
|
||||
private void ColorEditorWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
||||
{
|
||||
e.Cancel = true;
|
||||
this.Hide();
|
||||
}
|
||||
}
|
||||
}
|
@ -106,12 +106,31 @@
|
||||
<Reference Include="PresentationFramework" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Behaviors\DragAndDropReorderBehavior.cs" />
|
||||
<Compile Include="Behaviors\DragWindowBehavior.cs" />
|
||||
<Compile Include="ColorEditorWindow.xaml.cs">
|
||||
<DependentUpon>ColorEditorWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Common\RangeObservableCollection.cs" />
|
||||
<Compile Include="Controls\ColorFormatControl.xaml.cs">
|
||||
<DependentUpon>ColorFormatControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\ColorPickerControl.xaml.cs">
|
||||
<DependentUpon>ColorPickerControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\HSVColor.cs" />
|
||||
<Compile Include="Converters\ColorToBrushConverter.cs" />
|
||||
<Compile Include="Converters\ColorToStringConverter.cs" />
|
||||
<Compile Include="Converters\NumberToInvertedVisibilityConverter.cs" />
|
||||
<Compile Include="Converters\NumberToVisibilityConverter.cs" />
|
||||
<Compile Include="Helpers\ClipboardHelper.cs" />
|
||||
<Compile Include="Behaviors\GridEffectBehavior.cs" />
|
||||
<Compile Include="Constants\WindowConstant.cs" />
|
||||
<Compile Include="Helpers\ColorHelper.cs" />
|
||||
<Compile Include="Helpers\ColorRepresentationHelper.cs" />
|
||||
<Compile Include="Helpers\CustomLibraryThemeProvider.cs" />
|
||||
<Compile Include="Helpers\IThrottledActionInvoker.cs" />
|
||||
<Compile Include="Helpers\ThrottledActionInvoker.cs" />
|
||||
<Compile Include="Models\ColorFormatModel.cs" />
|
||||
<Compile Include="NativeMethods.cs" />
|
||||
<Compile Include="Settings\IUserSettings.cs" />
|
||||
<Compile Include="Settings\SettingItem`1.cs" />
|
||||
@ -121,6 +140,12 @@
|
||||
<Compile Include="Telemetry\ColorPickerCancelledEvent.cs" />
|
||||
<Compile Include="Telemetry\ColorPickerShowEvent.cs" />
|
||||
<Compile Include="Telemetry\ColorPickerZoomOpenedEvent.cs" />
|
||||
<Compile Include="ThemeManager.cs" />
|
||||
<Compile Include="ViewModelContracts\IColorEditorViewModel.cs" />
|
||||
<Compile Include="ViewModels\ColorEditorViewModel.cs" />
|
||||
<Compile Include="Views\ColorEditorView.xaml.cs">
|
||||
<DependentUpon>ColorEditorView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ZoomWindow.xaml.cs">
|
||||
<DependentUpon>ZoomWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@ -139,6 +164,18 @@
|
||||
<Compile Include="Views\ZoomView.xaml.cs">
|
||||
<DependentUpon>ZoomView.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Page Include="ColorEditorWindow.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Controls\ColorFormatControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Controls\ColorPickerControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
@ -173,6 +210,34 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Themes\Dark.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Themes\HighContrast1.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Themes\HighContrast2.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Themes\HighContrastBlack.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Themes\HighContrastWhite.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Themes\Light.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\ColorEditorView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Views\MainView.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
@ -205,7 +270,7 @@
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.*.resx" />
|
||||
@ -220,11 +285,17 @@
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ControlzEx">
|
||||
<Version>4.4.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers">
|
||||
<Version>3.3.0</Version>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="ModernWpfUI">
|
||||
<Version>0.9.2</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.IO.Abstractions">
|
||||
<Version>12.2.5</Version>
|
||||
</PackageReference>
|
||||
|
@ -0,0 +1,74 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace ColorPicker.Common
|
||||
{
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:File name should match first type name", Justification = "File name is correct, ignore generics")]
|
||||
public sealed class RangeObservableCollection<T> : ObservableCollection<T>
|
||||
{
|
||||
private object _collectionChangedLock = new object();
|
||||
private bool _suppressNotification;
|
||||
|
||||
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
lock (_collectionChangedLock)
|
||||
{
|
||||
if (!_suppressNotification)
|
||||
{
|
||||
base.OnCollectionChanged(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddRange(IEnumerable<T> list)
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(list));
|
||||
}
|
||||
|
||||
_suppressNotification = true;
|
||||
|
||||
foreach (T item in list)
|
||||
{
|
||||
Add(item);
|
||||
}
|
||||
|
||||
_suppressNotification = false;
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
|
||||
public void AddWithoutNotification(T item)
|
||||
{
|
||||
lock (_collectionChangedLock)
|
||||
{
|
||||
_suppressNotification = true;
|
||||
Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void ReleaseNotification()
|
||||
{
|
||||
lock (_collectionChangedLock)
|
||||
{
|
||||
_suppressNotification = false;
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearWithoutNotification()
|
||||
{
|
||||
lock (_collectionChangedLock)
|
||||
{
|
||||
_suppressNotification = true;
|
||||
Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
// 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.
|
||||
|
||||
namespace ColorPicker.Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// This class contains all assembly wide constants for windows and views
|
||||
/// </summary>
|
||||
public static class WindowConstant
|
||||
{
|
||||
/// <summary>
|
||||
/// The width of the color picker window
|
||||
/// </summary>
|
||||
public const double PickerWindowWidth = 240d;
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
<UserControl x:Class="ColorPicker.Controls.ColorFormatControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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:p="clr-namespace:ColorPicker.Properties"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Border x:Name="MainBorder"
|
||||
Margin="12,16,12,0"
|
||||
Width="308"
|
||||
Height="36"
|
||||
CornerRadius="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="{DynamicResource ColorControlBackgroundBrush}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="64"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="36"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock x:Name="FormatNameTextBlock"
|
||||
Opacity="0.4"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
Margin="8"
|
||||
FontWeight="SemiBold"
|
||||
FontSize="12"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<TextBox x:Name="ColorTextRepresentationTextBlock"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
FontFamily="Consolas"
|
||||
Grid.Column="1"
|
||||
FontSize="14"
|
||||
IsTabStop="False"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
IsReadOnly="True"
|
||||
Margin="8"
|
||||
VerticalAlignment="Center"
|
||||
Style="{DynamicResource TextBoxStyle}"
|
||||
AutomationProperties.LabeledBy="{Binding FormatNameTextBlock}"
|
||||
/>
|
||||
|
||||
<Button x:Name="CopyToClipboardButton"
|
||||
ToolTipService.ToolTip="{x:Static p:Resources.Copy_to_clipboard}"
|
||||
Background="{DynamicResource ColorControlBackgroundBrush}"
|
||||
Height="36"
|
||||
Width="36"
|
||||
Grid.Column="2"
|
||||
AutomationProperties.HelpText="{Binding ElementName=FormatNameTextBlock, Path=Text}"
|
||||
AutomationProperties.Name="{x:Static p:Resources.Copy_to_clipboard}">
|
||||
<Button.Content>
|
||||
<TextBlock FontFamily="Segoe MDL2 Assets"
|
||||
Text=""
|
||||
FontSize="12" />
|
||||
</Button.Content>
|
||||
<Button.Resources>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource DefaultButtonStyle}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Path=IsMouseOver, ElementName=MainBorder}" Value="False">
|
||||
<Setter Property="Opacity" Value="0"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Resources>
|
||||
</Button>
|
||||
</Grid>
|
||||
<Border.Effect>
|
||||
<DropShadowEffect BlurRadius="6" Opacity="0.24" ShadowDepth="1" />
|
||||
</Border.Effect>
|
||||
</Border>
|
||||
</UserControl>
|
@ -0,0 +1,106 @@
|
||||
// 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.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using ColorPicker.Helpers;
|
||||
using ColorPicker.Models;
|
||||
|
||||
namespace ColorPicker.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ColorFormatControl.xaml
|
||||
/// </summary>
|
||||
public partial class ColorFormatControl : UserControl
|
||||
{
|
||||
public static readonly DependencyProperty ColorFormatModelProperty = DependencyProperty.Register("ColorFormatModel", typeof(ColorFormatModel), typeof(ColorFormatControl), new PropertyMetadata(ColorFormatModelPropertyChanged));
|
||||
|
||||
public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register("SelectedColor", typeof(Color), typeof(ColorFormatControl), new PropertyMetadata(SelectedColorPropertyChanged));
|
||||
|
||||
public static readonly DependencyProperty ColorCopiedNotificationBorderProperty = DependencyProperty.Register("ColorCopiedNotificationBorder", typeof(FrameworkElement), typeof(ColorFormatControl), new PropertyMetadata(ColorCopiedBorderPropertyChanged));
|
||||
|
||||
private const int CopyIndicatorStayTimeInMs = 3000;
|
||||
private IThrottledActionInvoker _actionInvoker;
|
||||
private bool _copyIndicatorVisible;
|
||||
|
||||
public Color SelectedColor
|
||||
{
|
||||
get { return (Color)GetValue(SelectedColorProperty); }
|
||||
set { SetValue(SelectedColorProperty, value); }
|
||||
}
|
||||
|
||||
public ColorFormatModel ColorFormatModel
|
||||
{
|
||||
get { return (ColorFormatModel)GetValue(ColorFormatModelProperty); }
|
||||
set { SetValue(ColorFormatModelProperty, value); }
|
||||
}
|
||||
|
||||
public FrameworkElement ColorCopiedNotificationBorder
|
||||
{
|
||||
get { return (FrameworkElement)GetValue(ColorCopiedNotificationBorderProperty); }
|
||||
set { SetValue(ColorCopiedNotificationBorderProperty, value); }
|
||||
}
|
||||
|
||||
public ColorFormatControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
_actionInvoker = Bootstrapper.Container.GetExportedValue<IThrottledActionInvoker>();
|
||||
CopyToClipboardButton.Click += CopyToClipboardButton_Click;
|
||||
}
|
||||
|
||||
private void CopyToClipboardButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ClipboardHelper.CopyToClipboard(ColorTextRepresentationTextBlock.Text);
|
||||
if (!_copyIndicatorVisible)
|
||||
{
|
||||
AppearCopiedIndicator();
|
||||
}
|
||||
|
||||
_actionInvoker.ScheduleAction(() => HideCopiedIndicator(), CopyIndicatorStayTimeInMs);
|
||||
}
|
||||
|
||||
private static void SelectedColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
((ColorFormatControl)d).ColorTextRepresentationTextBlock.Text = ((ColorFormatControl)d).ColorFormatModel.Convert((Color)e.NewValue);
|
||||
}
|
||||
|
||||
private static void ColorFormatModelPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
((ColorFormatControl)d).FormatNameTextBlock.Text = ((ColorFormatModel)e.NewValue).FormatName;
|
||||
}
|
||||
|
||||
private static void ColorCopiedBorderPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
((ColorFormatControl)d).ColorCopiedNotificationBorder = (FrameworkElement)e.NewValue;
|
||||
}
|
||||
|
||||
private void AppearCopiedIndicator()
|
||||
{
|
||||
_copyIndicatorVisible = true;
|
||||
var opacityAppear = new DoubleAnimation(1.0, new Duration(TimeSpan.FromMilliseconds(300)));
|
||||
opacityAppear.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseInOut };
|
||||
var resize = new DoubleAnimation(56, new Duration(TimeSpan.FromMilliseconds(300)));
|
||||
|
||||
resize.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseInOut };
|
||||
ColorCopiedNotificationBorder.BeginAnimation(Border.OpacityProperty, opacityAppear);
|
||||
ColorCopiedNotificationBorder.BeginAnimation(Border.HeightProperty, resize);
|
||||
}
|
||||
|
||||
private void HideCopiedIndicator()
|
||||
{
|
||||
_copyIndicatorVisible = false;
|
||||
var opacityDisappear = new DoubleAnimation(0, new Duration(TimeSpan.FromMilliseconds(300)));
|
||||
opacityDisappear.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseInOut };
|
||||
var resize = new DoubleAnimation(0, new Duration(TimeSpan.FromMilliseconds(300)));
|
||||
|
||||
resize.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseInOut };
|
||||
ColorCopiedNotificationBorder.BeginAnimation(Border.OpacityProperty, opacityDisappear);
|
||||
ColorCopiedNotificationBorder.BeginAnimation(Border.HeightProperty, resize);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,290 @@
|
||||
<UserControl x:Class="ColorPicker.Controls.ColorPickerControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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:local="clr-namespace:ColorPicker.Controls"
|
||||
xmlns:p="clr-namespace:ColorPicker.Properties"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
mc:Ignorable="d"
|
||||
Height="350"
|
||||
Width="333">
|
||||
<StackPanel x:Name="PickerPanel"
|
||||
Orientation="Vertical"
|
||||
Background="{x:Null}" >
|
||||
<!--Top panel-->
|
||||
<Grid HorizontalAlignment="Stretch" Margin="12,0,12,0">
|
||||
<Grid.Effect>
|
||||
<DropShadowEffect BlurRadius="6" Opacity="0.32" ShadowDepth="2" />
|
||||
</Grid.Effect>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="36"/>
|
||||
<ColumnDefinition Width="36"/>
|
||||
<ColumnDefinition Width="165"/>
|
||||
<ColumnDefinition Width="36"/>
|
||||
<ColumnDefinition Width="36"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Button x:Name="colorVariation1Button"
|
||||
Grid.Column="0"
|
||||
TabIndex="4"
|
||||
ui:ControlHelper.CornerRadius="2,0,0,2"
|
||||
Background="LightPink"
|
||||
Click="ColorVariationButton_Click"
|
||||
AutomationProperties.Name="Color shade 1"
|
||||
Style="{DynamicResource ColorShadeButtonStyle}"/>
|
||||
<Button x:Name="colorVariation2Button"
|
||||
Grid.Column="1"
|
||||
ui:ControlHelper.CornerRadius="0"
|
||||
TabIndex="5"
|
||||
Background="LightPink"
|
||||
Click="ColorVariationButton_Click"
|
||||
AutomationProperties.Name="Color shade 2"
|
||||
Style="{DynamicResource ColorShadeButtonStyle}"/>
|
||||
<Button x:Name="colorVariation3Button"
|
||||
Grid.Column="3"
|
||||
TabIndex="7"
|
||||
ui:ControlHelper.CornerRadius="0"
|
||||
Background="LightPink"
|
||||
Click="ColorVariationButton_Click"
|
||||
AutomationProperties.Name="Color shade 3"
|
||||
Style="{DynamicResource ColorShadeButtonStyle}"/>
|
||||
<Button x:Name="colorVariation4Button"
|
||||
Grid.Column="4"
|
||||
TabIndex="8"
|
||||
ui:ControlHelper.CornerRadius="0,2,2,0"
|
||||
Background="LightPink"
|
||||
Click="ColorVariationButton_Click"
|
||||
AutomationProperties.Name="Color shade 5"
|
||||
Style="{DynamicResource ColorShadeButtonStyle}"/>
|
||||
<Button x:Name="CurrentColorButton"
|
||||
HorizontalAlignment="Left"
|
||||
Grid.Column="0"
|
||||
TabIndex="6"
|
||||
Grid.ColumnSpan="5"
|
||||
Opacity="1"
|
||||
ui:ControlHelper.CornerRadius="0"
|
||||
Background="Red"
|
||||
Width="165"
|
||||
Height="48"
|
||||
Margin="72,0,0,0"
|
||||
AutomationProperties.Name="{x:Static p:Resources.Selected_color}"
|
||||
AutomationProperties.HelpText="{x:Static p:Resources.Selected_color_helptext}"
|
||||
ToolTipService.ToolTip="{x:Static p:Resources.Selected_color_tooltip}"
|
||||
Click="CurrentColorButton_Click"
|
||||
Style="{DynamicResource ColorShadeButtonStyle}"/>
|
||||
</Grid>
|
||||
|
||||
<!--Details panel-->
|
||||
<Grid Margin="0,4,0,12"
|
||||
Height="0"
|
||||
Visibility="Collapsed"
|
||||
x:Name="detailsGrid">
|
||||
<Border Background="{DynamicResource PrimaryBackgroundBrush}"/>
|
||||
<StackPanel x:Name="detailsStackPanel"
|
||||
Opacity="0">
|
||||
|
||||
<Grid Margin="12,0,0,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="20"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="36"/>
|
||||
<RowDefinition Height="36"/>
|
||||
<RowDefinition Height="36"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Text="H"
|
||||
FontWeight="SemiBold"
|
||||
Margin="0,10,0,0"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<Border Grid.Column="1"
|
||||
Margin="0,12,12,0"
|
||||
x:Name="HueGradientGrid"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Height="24"
|
||||
AutomationProperties.Name="{x:Static p:Resources.Hue_slider}"
|
||||
Width="289"
|
||||
CornerRadius="2"
|
||||
MouseLeftButtonDown="HueGradientGrid_MouseLeftButtonDown"
|
||||
MouseMove="HueGradientGrid_MouseMove">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect BlurRadius="6" Opacity="0.32" ShadowDepth="2" />
|
||||
</Border.Effect>
|
||||
<Border VerticalAlignment="Stretch"
|
||||
Width="6"
|
||||
x:Name="hueGradientPointer"
|
||||
Margin="154,0,0,0"
|
||||
Background="#88FFFFFF"
|
||||
BorderBrush="Black"
|
||||
CornerRadius="2"
|
||||
BorderThickness="1"
|
||||
HorizontalAlignment="Left"/>
|
||||
</Border>
|
||||
|
||||
<TextBlock Text="S"
|
||||
Grid.Row="1"
|
||||
Margin="0,10,0,0"
|
||||
FontWeight="SemiBold"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<Border HorizontalAlignment="Left"
|
||||
Grid.Column="1"
|
||||
Grid.Row="1"
|
||||
Margin="0,12,12,0"
|
||||
VerticalAlignment="Center"
|
||||
Height="24"
|
||||
AutomationProperties.Name="{x:Static p:Resources.Saturation_slider}"
|
||||
x:Name="SaturationGradientGrid"
|
||||
Width="289"
|
||||
CornerRadius="2"
|
||||
MouseLeftButtonDown="SaturationGradientGrid_MouseLeftButtonDown"
|
||||
MouseMove="SaturationGradientGrid_MouseMove">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect BlurRadius="6" Opacity="0.32" ShadowDepth="2" />
|
||||
</Border.Effect>
|
||||
<Border.Background>
|
||||
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0, 0.5">
|
||||
<GradientStop x:Name="SaturationStartColor" Color="Black"/>
|
||||
<GradientStop x:Name="SaturationStopColor" Color="Red" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
</Border.Background>
|
||||
<Border HorizontalAlignment="Left"
|
||||
x:Name="saturationGradientPointer"
|
||||
BorderBrush="Black"
|
||||
BorderThickness="1"
|
||||
Margin="154,0,0,0"
|
||||
CornerRadius="2"
|
||||
Width="6"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="#88FFFFFF"/>
|
||||
</Border>
|
||||
|
||||
<TextBlock Text="V"
|
||||
Grid.Row="2"
|
||||
Margin="0,10,0,0"
|
||||
FontWeight="SemiBold"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<Border HorizontalAlignment="Left"
|
||||
Grid.Column="1"
|
||||
Grid.Row="2"
|
||||
Margin="0,12,12,0"
|
||||
Height="24"
|
||||
VerticalAlignment="Center"
|
||||
CornerRadius="2"
|
||||
x:Name="ValueGradientGrid"
|
||||
Width="289"
|
||||
AutomationProperties.Name="{x:Static p:Resources.Value_slider}"
|
||||
MouseLeftButtonDown="ValueGradientGrid_MouseLeftButtonDown"
|
||||
MouseMove="ValueGradientGrid_MouseMove">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect BlurRadius="6" Opacity="0.32" ShadowDepth="2" />
|
||||
</Border.Effect>
|
||||
<Border.Background>
|
||||
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0, 0.5">
|
||||
<GradientStop x:Name="ValueStartColor" Color="Red"/>
|
||||
<GradientStop x:Name="ValueStopColor" Color="White" Offset="1"/>
|
||||
</LinearGradientBrush>
|
||||
</Border.Background>
|
||||
<Border HorizontalAlignment="Left"
|
||||
x:Name="valueGradientPointer"
|
||||
BorderBrush="Black"
|
||||
BorderThickness="1"
|
||||
Margin="154,0,0,0"
|
||||
Width="6"
|
||||
CornerRadius="2"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="#88FFFFFF"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<Grid HorizontalAlignment="Stretch" Margin="12,16,12,8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="20"/>
|
||||
<ColumnDefinition Width="68"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="36"/>
|
||||
<RowDefinition Height="36"/>
|
||||
<RowDefinition Height="36"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Text="R"
|
||||
FontWeight="SemiBold"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBox x:Name="RTextBox"
|
||||
Margin="0,0,0,0"
|
||||
Grid.Column="1"
|
||||
Height="32"
|
||||
AutomationProperties.Name="{x:Static p:Resources.Red_value}"
|
||||
TextChanged="RGBTextBoxes_TextChanged"
|
||||
TextWrapping="Wrap"/>
|
||||
|
||||
<TextBlock Text="G"
|
||||
FontWeight="SemiBold"
|
||||
Grid.Row="1"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<TextBox x:Name="GTextBox"
|
||||
Width="68"
|
||||
Height="32"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
AutomationProperties.Name="{x:Static p:Resources.Green_value}"
|
||||
TextChanged="RGBTextBoxes_TextChanged"
|
||||
TextWrapping="Wrap"/>
|
||||
|
||||
<TextBlock Text="B"
|
||||
FontWeight="SemiBold"
|
||||
Grid.Row="2"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<TextBox x:Name="BTextBox"
|
||||
Width="68"
|
||||
Height="32"
|
||||
Grid.Column="1"
|
||||
Grid.Row="2"
|
||||
AutomationProperties.Name="{x:Static p:Resources.Blue_value}"
|
||||
TextChanged="RGBTextBoxes_TextChanged"
|
||||
TextWrapping="Wrap"/>
|
||||
|
||||
<TextBlock Text="HEX"
|
||||
Grid.Column="2"
|
||||
HorizontalAlignment="Right"
|
||||
FontWeight="SemiBold"
|
||||
VerticalAlignment="Center"/>
|
||||
<TextBox x:Name="HexCode"
|
||||
HorizontalAlignment="Stretch"
|
||||
Margin="8,0,0,0"
|
||||
Height="32"
|
||||
Grid.Column="3"
|
||||
AutomationProperties.Name="{x:Static p:Resources.Hex_value}"
|
||||
TextChanged="HexCode_TextChanged"
|
||||
TextWrapping="Wrap"/>
|
||||
</Grid>
|
||||
<WrapPanel HorizontalAlignment="Right"
|
||||
Margin="0,0,0,0"
|
||||
VerticalAlignment="Top">
|
||||
<Button x:Name="CancelButton"
|
||||
Click="CancelButton_Click"
|
||||
AutomationProperties.Name="{x:Static p:Resources.Cancel}"
|
||||
Content="Cancel"
|
||||
Width="80"/>
|
||||
<Button Margin="12,0,12,0"
|
||||
x:Name="OKButton"
|
||||
Click="OKButton_Click"
|
||||
Style="{StaticResource AccentButtonStyle}"
|
||||
AutomationProperties.Name="{x:Static p:Resources.OK}"
|
||||
Content="OK"
|
||||
Width="80"/>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
@ -0,0 +1,399 @@
|
||||
// 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.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using ColorPicker.Helpers;
|
||||
using ModernWpf.Controls.Primitives;
|
||||
|
||||
namespace ColorPicker.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ColorPickerControl.xaml
|
||||
/// </summary>
|
||||
public partial class ColorPickerControl : UserControl
|
||||
{
|
||||
private const int GradientPointerHalfWidth = 3;
|
||||
private double _currH = 360;
|
||||
private double _currS = 1;
|
||||
private double _currV = 1;
|
||||
private bool _ignoreHexChanges;
|
||||
private bool _ignoreRGBChanges;
|
||||
private bool _ignoreGradientsChanges;
|
||||
private bool _isCollapsed = true;
|
||||
private Color _originalColor;
|
||||
private Color _currentColor;
|
||||
|
||||
public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register("SelectedColor", typeof(Color), typeof(ColorPickerControl), new PropertyMetadata(SelectedColorPropertyChanged));
|
||||
|
||||
public static readonly DependencyProperty SelectedColorChangeCommandProperty = DependencyProperty.Register("SelectedColorChangedCommand", typeof(ICommand), typeof(ColorPickerControl));
|
||||
|
||||
public ColorPickerControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
UpdateHueGradient(1, 1);
|
||||
}
|
||||
|
||||
public Color SelectedColor
|
||||
{
|
||||
get { return (Color)GetValue(SelectedColorProperty); }
|
||||
set { SetValue(SelectedColorProperty, value); }
|
||||
}
|
||||
|
||||
public ICommand SelectedColorChangedCommand
|
||||
{
|
||||
get { return (ICommand)GetValue(SelectedColorChangeCommandProperty); }
|
||||
set { SetValue(SelectedColorChangeCommandProperty, value); }
|
||||
}
|
||||
|
||||
private static void SelectedColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var newColor = (Color)e.NewValue;
|
||||
((ColorPickerControl)d)._originalColor = ((ColorPickerControl)d)._currentColor = newColor;
|
||||
var newColorBackground = new SolidColorBrush(newColor);
|
||||
((ColorPickerControl)d).CurrentColorButton.Background = newColorBackground;
|
||||
|
||||
((ColorPickerControl)d)._ignoreHexChanges = true;
|
||||
((ColorPickerControl)d)._ignoreRGBChanges = true;
|
||||
((ColorPickerControl)d).HexCode.Text = ColorToHex(newColor);
|
||||
((ColorPickerControl)d).RTextBox.Text = newColor.R.ToString(CultureInfo.InvariantCulture);
|
||||
((ColorPickerControl)d).GTextBox.Text = newColor.G.ToString(CultureInfo.InvariantCulture);
|
||||
((ColorPickerControl)d).BTextBox.Text = newColor.B.ToString(CultureInfo.InvariantCulture);
|
||||
((ColorPickerControl)d).SetColorFromTextBoxes(System.Drawing.Color.FromArgb(newColor.R, newColor.G, newColor.B));
|
||||
((ColorPickerControl)d)._ignoreRGBChanges = false;
|
||||
((ColorPickerControl)d)._ignoreHexChanges = false;
|
||||
|
||||
var hsv = ColorHelper.ConvertToHSVColor(System.Drawing.Color.FromArgb(newColor.R, newColor.G, newColor.B));
|
||||
|
||||
SetColorVariationsForCurrentColor(d, hsv);
|
||||
}
|
||||
|
||||
private void UpdateHueGradient(double saturation, double value)
|
||||
{
|
||||
var g6 = HSVColor.HueSpectrum(saturation, value);
|
||||
|
||||
var gradientBrush = new LinearGradientBrush();
|
||||
gradientBrush.StartPoint = new Point(0, 0);
|
||||
gradientBrush.EndPoint = new Point(1, 0);
|
||||
for (int i = 0; i < g6.Length; i++)
|
||||
{
|
||||
var stop = new GradientStop(g6[i], i * 0.16);
|
||||
gradientBrush.GradientStops.Add(stop);
|
||||
}
|
||||
|
||||
HueGradientGrid.Background = gradientBrush;
|
||||
}
|
||||
|
||||
private static void SetColorVariationsForCurrentColor(DependencyObject d, (double hue, double saturation, double value) hsv)
|
||||
{
|
||||
var hueCoefficient = 0;
|
||||
var hueCoefficient2 = 0;
|
||||
if (1 - hsv.value < 0.15)
|
||||
{
|
||||
hueCoefficient = 1;
|
||||
}
|
||||
|
||||
if (hsv.value - 0.3 < 0)
|
||||
{
|
||||
hueCoefficient2 = 1;
|
||||
}
|
||||
|
||||
var s = hsv.saturation;
|
||||
|
||||
((ColorPickerControl)d).colorVariation1Button.Background = new SolidColorBrush(HSVColor.RGBFromHSV(Math.Min(hsv.hue + (hueCoefficient * 8), 360), s, Math.Min(hsv.value + 0.3, 1)));
|
||||
((ColorPickerControl)d).colorVariation2Button.Background = new SolidColorBrush(HSVColor.RGBFromHSV(Math.Min(hsv.hue + (hueCoefficient * 4), 360), s, Math.Min(hsv.value + 0.15, 1)));
|
||||
|
||||
((ColorPickerControl)d).colorVariation3Button.Background = new SolidColorBrush(HSVColor.RGBFromHSV(Math.Max(hsv.hue - (hueCoefficient2 * 4), 0), s, Math.Max(hsv.value - 0.2, 0)));
|
||||
((ColorPickerControl)d).colorVariation4Button.Background = new SolidColorBrush(HSVColor.RGBFromHSV(Math.Max(hsv.hue - (hueCoefficient2 * 8), 0), s, Math.Max(hsv.value - 0.3, 0)));
|
||||
}
|
||||
|
||||
private void UpdateValueColorGradient(double posX)
|
||||
{
|
||||
valueGradientPointer.Margin = new Thickness(posX - GradientPointerHalfWidth, 0, 0, 0);
|
||||
|
||||
_currV = posX / ValueGradientGrid.Width;
|
||||
|
||||
UpdateHueGradient(_currS, _currV);
|
||||
|
||||
SaturationStartColor.Color = HSVColor.RGBFromHSV(_currH, 0f, _currV);
|
||||
SaturationStopColor.Color = HSVColor.RGBFromHSV(_currH, 1f, _currV);
|
||||
}
|
||||
|
||||
private void UpdateSaturationColorGradient(double posX)
|
||||
{
|
||||
saturationGradientPointer.Margin = new Thickness(posX - GradientPointerHalfWidth, 0, 0, 0);
|
||||
|
||||
_currS = posX / SaturationGradientGrid.Width;
|
||||
|
||||
UpdateHueGradient(_currS, _currV);
|
||||
|
||||
ValueStartColor.Color = HSVColor.RGBFromHSV(_currH, _currS, 0f);
|
||||
ValueStopColor.Color = HSVColor.RGBFromHSV(_currH, _currS, 1f);
|
||||
}
|
||||
|
||||
private void UpdateHueColorGradient(double posX)
|
||||
{
|
||||
hueGradientPointer.Margin = new Thickness(posX - GradientPointerHalfWidth, 0, 0, 0);
|
||||
|
||||
_currH = posX / HueGradientGrid.Width * 360;
|
||||
|
||||
SaturationStartColor.Color = HSVColor.RGBFromHSV(_currH, 0f, _currV);
|
||||
SaturationStopColor.Color = HSVColor.RGBFromHSV(_currH, 1f, _currV);
|
||||
|
||||
ValueStartColor.Color = HSVColor.RGBFromHSV(_currH, _currS, 0f);
|
||||
ValueStopColor.Color = HSVColor.RGBFromHSV(_currH, _currS, 1f);
|
||||
}
|
||||
|
||||
private void UpdateTextBoxesAndCurrentColor(Color currentColor)
|
||||
{
|
||||
if (!_ignoreHexChanges)
|
||||
{
|
||||
HexCode.Text = ColorToHex(currentColor);
|
||||
}
|
||||
|
||||
if (!_ignoreRGBChanges)
|
||||
{
|
||||
RTextBox.Text = currentColor.R.ToString(CultureInfo.InvariantCulture);
|
||||
GTextBox.Text = currentColor.G.ToString(CultureInfo.InvariantCulture);
|
||||
BTextBox.Text = currentColor.B.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
_currentColor = currentColor;
|
||||
CurrentColorButton.Background = new SolidColorBrush(currentColor);
|
||||
}
|
||||
|
||||
private void CurrentColorButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ShowDetails();
|
||||
}
|
||||
|
||||
private void ShowDetails()
|
||||
{
|
||||
if (_isCollapsed)
|
||||
{
|
||||
detailsGrid.Visibility = Visibility.Visible;
|
||||
_isCollapsed = false;
|
||||
|
||||
var opacityAppear = new DoubleAnimation(1.0, new Duration(TimeSpan.FromMilliseconds(300)));
|
||||
opacityAppear.EasingFunction = new QuadraticEase() { EasingMode = EasingMode.EaseInOut };
|
||||
|
||||
var resize = new DoubleAnimation(400, new Duration(TimeSpan.FromMilliseconds(300)));
|
||||
resize.EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseInOut };
|
||||
|
||||
var resizeColor = new DoubleAnimation(309, new Duration(TimeSpan.FromMilliseconds(250)));
|
||||
resizeColor.EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseInOut };
|
||||
|
||||
var moveColor = new ThicknessAnimation(new Thickness(0), new Duration(TimeSpan.FromMilliseconds(250)));
|
||||
moveColor.EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseInOut };
|
||||
|
||||
ControlHelper.SetCornerRadius(CurrentColorButton, new CornerRadius(2));
|
||||
CurrentColorButton.BeginAnimation(Button.WidthProperty, resizeColor);
|
||||
CurrentColorButton.BeginAnimation(Button.MarginProperty, moveColor);
|
||||
detailsStackPanel.BeginAnimation(StackPanel.OpacityProperty, opacityAppear);
|
||||
detailsGrid.BeginAnimation(Grid.HeightProperty, resize);
|
||||
}
|
||||
}
|
||||
|
||||
private void HideDetails()
|
||||
{
|
||||
if (!_isCollapsed)
|
||||
{
|
||||
_isCollapsed = true;
|
||||
|
||||
var opacityAppear = new DoubleAnimation(0, new Duration(TimeSpan.FromMilliseconds(150)));
|
||||
opacityAppear.EasingFunction = new QuadraticEase() { EasingMode = EasingMode.EaseInOut };
|
||||
|
||||
var resize = new DoubleAnimation(0, new Duration(TimeSpan.FromMilliseconds(150)));
|
||||
resize.EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseInOut };
|
||||
|
||||
var resizeColor = new DoubleAnimation(165, new Duration(TimeSpan.FromMilliseconds(150)));
|
||||
resizeColor.EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseInOut };
|
||||
|
||||
var moveColor = new ThicknessAnimation(new Thickness(72, 0, 0, 0), new Duration(TimeSpan.FromMilliseconds(150)));
|
||||
moveColor.EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseInOut };
|
||||
|
||||
ControlHelper.SetCornerRadius(CurrentColorButton, new CornerRadius(0));
|
||||
CurrentColorButton.BeginAnimation(Button.WidthProperty, resizeColor);
|
||||
CurrentColorButton.BeginAnimation(Button.MarginProperty, moveColor);
|
||||
detailsStackPanel.BeginAnimation(Window.OpacityProperty, opacityAppear);
|
||||
detailsGrid.BeginAnimation(Grid.HeightProperty, resize);
|
||||
detailsGrid.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
private void OKButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
HideDetails();
|
||||
|
||||
SelectedColorChangedCommand.Execute(_currentColor);
|
||||
}
|
||||
|
||||
private void CancelButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
HideDetails();
|
||||
|
||||
// Revert to original color
|
||||
var originalColorBackground = new SolidColorBrush(_originalColor);
|
||||
CurrentColorButton.Background = originalColorBackground;
|
||||
|
||||
HexCode.Text = ColorToHex(_originalColor);
|
||||
}
|
||||
|
||||
private void ColorVariationButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var selectedColor = ((SolidColorBrush)((Button)sender).Background).Color;
|
||||
SelectedColorChangedCommand.Execute(selectedColor);
|
||||
}
|
||||
|
||||
private void ValueGradientGrid_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
var pos = GetMousePositionWithinGrid(sender as Border);
|
||||
UpdateValueColorGradient(pos.X);
|
||||
_ignoreGradientsChanges = true;
|
||||
UpdateTextBoxesAndCurrentColor(HSVColor.RGBFromHSV(_currH, _currS, _currV));
|
||||
_ignoreGradientsChanges = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ValueGradientGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
var pos = GetMousePositionWithinGrid(sender as Border);
|
||||
UpdateValueColorGradient(pos.X);
|
||||
_ignoreGradientsChanges = true;
|
||||
UpdateTextBoxesAndCurrentColor(HSVColor.RGBFromHSV(_currH, _currS, _currV));
|
||||
_ignoreGradientsChanges = false;
|
||||
}
|
||||
|
||||
private void SaturationGradientGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
var pos = GetMousePositionWithinGrid(sender as Border);
|
||||
UpdateSaturationColorGradient(pos.X);
|
||||
_ignoreGradientsChanges = true;
|
||||
UpdateTextBoxesAndCurrentColor(HSVColor.RGBFromHSV(_currH, _currS, _currV));
|
||||
_ignoreGradientsChanges = false;
|
||||
}
|
||||
|
||||
private void SaturationGradientGrid_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
var pos = GetMousePositionWithinGrid(sender as Border);
|
||||
UpdateSaturationColorGradient(pos.X);
|
||||
_ignoreGradientsChanges = true;
|
||||
UpdateTextBoxesAndCurrentColor(HSVColor.RGBFromHSV(_currH, _currS, _currV));
|
||||
_ignoreGradientsChanges = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void HueGradientGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
var pos = GetMousePositionWithinGrid(sender as Border);
|
||||
UpdateHueColorGradient(pos.X);
|
||||
_ignoreGradientsChanges = true;
|
||||
UpdateTextBoxesAndCurrentColor(HSVColor.RGBFromHSV(_currH, _currS, _currV));
|
||||
_ignoreGradientsChanges = false;
|
||||
}
|
||||
|
||||
private void HueGradientGrid_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
var pos = GetMousePositionWithinGrid(sender as Border);
|
||||
UpdateHueColorGradient(pos.X);
|
||||
_ignoreGradientsChanges = true;
|
||||
UpdateTextBoxesAndCurrentColor(HSVColor.RGBFromHSV(_currH, _currS, _currV));
|
||||
_ignoreGradientsChanges = false;
|
||||
}
|
||||
}
|
||||
|
||||
private static Point GetMousePositionWithinGrid(Border border)
|
||||
{
|
||||
var pos = System.Windows.Input.Mouse.GetPosition(border);
|
||||
if (pos.X < 0)
|
||||
{
|
||||
pos.X = 0;
|
||||
}
|
||||
|
||||
if (pos.X > border.Width)
|
||||
{
|
||||
pos.X = border.Width;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
private void HexCode_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
var newValue = (sender as TextBox).Text;
|
||||
|
||||
// support hex with 3 and 6 characters
|
||||
var reg = new Regex("^#([0-9A-F]{3}){1,2}$");
|
||||
|
||||
if (!reg.IsMatch(newValue))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_ignoreHexChanges)
|
||||
{
|
||||
var converter = new System.Drawing.ColorConverter();
|
||||
|
||||
var color = (System.Drawing.Color)converter.ConvertFromString(HexCode.Text);
|
||||
_ignoreHexChanges = true;
|
||||
SetColorFromTextBoxes(color);
|
||||
_ignoreHexChanges = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void RGBTextBoxes_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
var validNumber = int.TryParse((sender as TextBox).Text, out int result);
|
||||
if (!validNumber || result < 0 || result > 255)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_ignoreRGBChanges)
|
||||
{
|
||||
var r = byte.Parse(RTextBox.Text, CultureInfo.InvariantCulture);
|
||||
var g = byte.Parse(GTextBox.Text, CultureInfo.InvariantCulture);
|
||||
var b = byte.Parse(BTextBox.Text, CultureInfo.InvariantCulture);
|
||||
_ignoreRGBChanges = true;
|
||||
SetColorFromTextBoxes(System.Drawing.Color.FromArgb(r, g, b));
|
||||
_ignoreRGBChanges = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetColorFromTextBoxes(System.Drawing.Color color)
|
||||
{
|
||||
if (!_ignoreGradientsChanges)
|
||||
{
|
||||
var hsv = ColorHelper.ConvertToHSVColor(color);
|
||||
|
||||
var huePosition = (hsv.hue / 360) * HueGradientGrid.Width;
|
||||
var saturationPosition = hsv.saturation * SaturationGradientGrid.Width;
|
||||
var valuePosition = hsv.value * ValueGradientGrid.Width;
|
||||
UpdateHueColorGradient(huePosition);
|
||||
UpdateSaturationColorGradient(saturationPosition);
|
||||
UpdateValueColorGradient(valuePosition);
|
||||
}
|
||||
|
||||
UpdateTextBoxesAndCurrentColor(Color.FromRgb(color.R, color.G, color.B));
|
||||
}
|
||||
|
||||
private static string ColorToHex(Color color)
|
||||
{
|
||||
return "#" + BitConverter.ToString(new byte[] { color.R, color.G, color.B }).Replace("-", string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
87
src/modules/colorPicker/ColorPickerUI/Controls/HSVColor.cs
Normal file
87
src/modules/colorPicker/ColorPickerUI/Controls/HSVColor.cs
Normal file
@ -0,0 +1,87 @@
|
||||
// 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.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
|
||||
namespace ColorPicker.Controls
|
||||
{
|
||||
public static class HSVColor
|
||||
{
|
||||
public static Color[] GetSpectrum()
|
||||
{
|
||||
var rgbs = new Color[360];
|
||||
|
||||
for (int h = 0; h < 360; h++)
|
||||
{
|
||||
rgbs[h] = RGBFromHSV(h, 1f, 1f);
|
||||
}
|
||||
|
||||
return rgbs;
|
||||
}
|
||||
|
||||
public static Color[] HueSpectrum(double saturation, double value)
|
||||
{
|
||||
var rgbs = new Color[7];
|
||||
|
||||
for (int h = 0; h < 7; h++)
|
||||
{
|
||||
rgbs[h] = RGBFromHSV(h * 60, saturation, value);
|
||||
}
|
||||
|
||||
return rgbs;
|
||||
}
|
||||
|
||||
public static Color RGBFromHSV(double h, double s, double v)
|
||||
{
|
||||
if (h > 360 || h < 0 || s > 1 || s < 0 || v > 1 || v < 0)
|
||||
{
|
||||
return Color.FromRgb(0, 0, 0);
|
||||
}
|
||||
|
||||
double c = v * s;
|
||||
double x = c * (1 - Math.Abs(((h / 60) % 2) - 1));
|
||||
double m = v - c;
|
||||
|
||||
double r = 0, g = 0, b = 0;
|
||||
|
||||
if (h < 60)
|
||||
{
|
||||
r = c;
|
||||
g = x;
|
||||
}
|
||||
else if (h < 120)
|
||||
{
|
||||
r = x;
|
||||
g = c;
|
||||
}
|
||||
else if (h < 180)
|
||||
{
|
||||
g = c;
|
||||
b = x;
|
||||
}
|
||||
else if (h < 240)
|
||||
{
|
||||
g = x;
|
||||
b = c;
|
||||
}
|
||||
else if (h < 300)
|
||||
{
|
||||
r = x;
|
||||
b = c;
|
||||
}
|
||||
else if (h <= 360)
|
||||
{
|
||||
r = c;
|
||||
b = x;
|
||||
}
|
||||
|
||||
return Color.FromRgb((byte)((r + m) * 255), (byte)((g + m) * 255), (byte)((b + m) * 255));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
// 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.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace ColorPicker.Converters
|
||||
{
|
||||
public class ColorToBrushConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
var color = (Color)value;
|
||||
return new SolidColorBrush(color);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
// 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.Globalization;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace ColorPicker.Converters
|
||||
{
|
||||
public class ColorToStringConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
var color = (Color)value;
|
||||
return "RGB(" + color.R + "," + color.G + "," + color.B + ")";
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
// 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.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ColorPicker.Converters
|
||||
{
|
||||
public class NumberToInvertedVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if ((int)value <= 0)
|
||||
{
|
||||
return Visibility.Visible;
|
||||
}
|
||||
|
||||
return Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
// 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.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ColorPicker.Converters
|
||||
{
|
||||
public class NumberToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if ((int)value <= 0)
|
||||
{
|
||||
return Visibility.Collapsed;
|
||||
}
|
||||
|
||||
return Visibility.Visible;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -5,16 +5,21 @@
|
||||
using System;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Windows;
|
||||
using ColorPicker.ViewModelContracts;
|
||||
|
||||
namespace ColorPicker.Helpers
|
||||
{
|
||||
[Export(typeof(AppStateHandler))]
|
||||
public class AppStateHandler
|
||||
{
|
||||
private readonly IColorEditorViewModel _colorEditorViewModel;
|
||||
private ColorEditorWindow _colorEditorWindow;
|
||||
|
||||
[ImportingConstructor]
|
||||
public AppStateHandler()
|
||||
public AppStateHandler(IColorEditorViewModel colorEditorViewModel)
|
||||
{
|
||||
Application.Current.MainWindow.Closed += MainWindow_Closed;
|
||||
_colorEditorViewModel = colorEditorViewModel;
|
||||
}
|
||||
|
||||
public event EventHandler AppShown;
|
||||
@ -37,6 +42,19 @@ namespace ColorPicker.Helpers
|
||||
AppHidden?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public void ShowColorPickerEditor()
|
||||
{
|
||||
if (_colorEditorWindow == null)
|
||||
{
|
||||
_colorEditorWindow = new ColorEditorWindow();
|
||||
_colorEditorWindow.Content = _colorEditorViewModel;
|
||||
_colorEditorViewModel.OpenColorPickerRequested += ColorEditorViewModel_OpenColorPickerRequested;
|
||||
}
|
||||
|
||||
_colorEditorViewModel.Initialize();
|
||||
_colorEditorWindow.Show();
|
||||
}
|
||||
|
||||
public static void SetTopMost()
|
||||
{
|
||||
Application.Current.MainWindow.Topmost = false;
|
||||
@ -47,5 +65,11 @@ namespace ColorPicker.Helpers
|
||||
{
|
||||
AppClosed?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void ColorEditorViewModel_OpenColorPickerRequested(object sender, EventArgs e)
|
||||
{
|
||||
ShowColorPicker();
|
||||
_colorEditorWindow.Hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,42 @@
|
||||
// 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.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
namespace ColorPicker.Helpers
|
||||
{
|
||||
public static class ClipboardHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Defined error code for "clipboard can't open"
|
||||
/// </summary>
|
||||
private const uint ErrorCodeClipboardCantOpen = 0x800401D0;
|
||||
|
||||
public static void CopyToClipboard(string colorRepresentationToCopy)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(colorRepresentationToCopy))
|
||||
{
|
||||
// nasty hack - sometimes clipboard can be in use and it will raise and exception
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
Clipboard.SetText(colorRepresentationToCopy);
|
||||
break;
|
||||
}
|
||||
catch (COMException ex)
|
||||
{
|
||||
if ((uint)ex.ErrorCode != ErrorCodeClipboardCantOpen)
|
||||
{
|
||||
Logger.LogError("Failed to set text into clipboard", ex);
|
||||
}
|
||||
}
|
||||
|
||||
System.Threading.Thread.Sleep(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,18 @@ namespace ColorPicker.Helpers
|
||||
/// </summary>
|
||||
internal static class ColorRepresentationHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Return a <see cref="string"/> representation of a given <see cref="Color"/>
|
||||
/// </summary>
|
||||
/// <param name="color">The <see cref="Color"/> for the presentation</param>
|
||||
/// <param name="colorRepresentationType">The type of the representation</param>
|
||||
/// <returns>A <see cref="string"/> representation of a color</returns>
|
||||
internal static string GetStringRepresentationFromMediaColor(System.Windows.Media.Color color, ColorRepresentationType colorRepresentationType)
|
||||
{
|
||||
var drawingcolor = Color.FromArgb(color.A, color.R, color.G, color.B);
|
||||
return GetStringRepresentation(drawingcolor, colorRepresentationType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a <see cref="string"/> representation of a given <see cref="Color"/>
|
||||
/// </summary>
|
||||
|
@ -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 ColorPicker.Helpers
|
||||
{
|
||||
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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -11,6 +11,7 @@ namespace ColorPicker.Helpers
|
||||
[Export(typeof(IThrottledActionInvoker))]
|
||||
public sealed class ThrottledActionInvoker : IThrottledActionInvoker
|
||||
{
|
||||
private object _invokerLock = new object();
|
||||
private Action _actionToRun;
|
||||
|
||||
private DispatcherTimer _timer;
|
||||
@ -23,20 +24,27 @@ namespace ColorPicker.Helpers
|
||||
|
||||
public void ScheduleAction(Action action, int milliseconds)
|
||||
{
|
||||
if (_timer.IsEnabled)
|
||||
lock (_invokerLock)
|
||||
{
|
||||
_timer.Stop();
|
||||
if (_timer.IsEnabled)
|
||||
{
|
||||
_timer.Stop();
|
||||
}
|
||||
|
||||
_actionToRun = action;
|
||||
_timer.Interval = new TimeSpan(0, 0, 0, 0, milliseconds);
|
||||
|
||||
_timer.Start();
|
||||
}
|
||||
|
||||
_actionToRun = action;
|
||||
_timer.Interval = new TimeSpan(0, 0, 0, 0, milliseconds);
|
||||
|
||||
_timer.Start();
|
||||
}
|
||||
|
||||
private void Timer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
_actionToRun.Invoke();
|
||||
lock (_invokerLock)
|
||||
{
|
||||
_timer.Stop();
|
||||
_actionToRun.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ using System.Windows.Input;
|
||||
using ColorPicker.Helpers;
|
||||
using ColorPicker.Settings;
|
||||
using ColorPicker.Telemetry;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using static ColorPicker.NativeMethods;
|
||||
@ -92,7 +93,14 @@ namespace ColorPicker.Keyboard
|
||||
|
||||
if (ArraysAreSame(currentlyPressedKeys, _activationKeys))
|
||||
{
|
||||
_appStateHandler.ShowColorPicker();
|
||||
if (_userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenEditor)
|
||||
{
|
||||
_appStateHandler.ShowColorPickerEditor();
|
||||
}
|
||||
else
|
||||
{
|
||||
_appStateHandler.ShowColorPicker();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,11 +3,18 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:constants="clr-namespace:ColorPicker.Constants"
|
||||
mc:Ignorable="d"
|
||||
xmlns:e="http://schemas.microsoft.com/expression/2010/interactivity"
|
||||
xmlns:behaviors="clr-namespace:ColorPicker.Behaviors"
|
||||
Title="Color Picker" Height="50" Width="{x:Static constants:WindowConstant.PickerWindowWidth}" WindowStyle="None" Opacity="0.01" ShowInTaskbar="False" ResizeMode="NoResize" Topmost="True" Background="Transparent" AllowsTransparency="True">
|
||||
Height="64"
|
||||
WindowStyle="None"
|
||||
Opacity="0.01"
|
||||
ShowInTaskbar="False"
|
||||
ResizeMode="NoResize"
|
||||
Topmost="True"
|
||||
Background="Transparent"
|
||||
SizeToContent="Width"
|
||||
AllowsTransparency="True">
|
||||
<e:Interaction.Behaviors>
|
||||
<behaviors:ChangeWindowPositionBehavior/>
|
||||
<behaviors:AppearAnimationBehavior/>
|
||||
|
@ -0,0 +1,16 @@
|
||||
// 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.Windows.Media;
|
||||
|
||||
namespace ColorPicker.Models
|
||||
{
|
||||
public class ColorFormatModel
|
||||
{
|
||||
public string FormatName { get; set; }
|
||||
|
||||
public Func<Color, string> Convert { get; set; }
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ namespace ColorPicker.Properties {
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
public class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
@ -36,7 +36,7 @@ namespace ColorPicker.Properties {
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
public static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ColorPicker.Properties.Resources", typeof(Resources).Assembly);
|
||||
@ -51,7 +51,7 @@ namespace ColorPicker.Properties {
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
public static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
@ -59,5 +59,176 @@ namespace ColorPicker.Properties {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Blue value.
|
||||
/// </summary>
|
||||
public static string Blue_value {
|
||||
get {
|
||||
return ResourceManager.GetString("Blue_value", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cancel.
|
||||
/// </summary>
|
||||
public static string Cancel {
|
||||
get {
|
||||
return ResourceManager.GetString("Cancel", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Copied to clipboard.
|
||||
/// </summary>
|
||||
public static string Copied_to_clipboard {
|
||||
get {
|
||||
return ResourceManager.GetString("Copied_to_clipboard", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Copy to clipboard.
|
||||
/// </summary>
|
||||
public static string Copy_to_clipboard {
|
||||
get {
|
||||
return ResourceManager.GetString("Copy_to_clipboard", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Color Picker editor.
|
||||
/// </summary>
|
||||
public static string cp_editor {
|
||||
get {
|
||||
return ResourceManager.GetString("cp_editor", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Green value.
|
||||
/// </summary>
|
||||
public static string Green_value {
|
||||
get {
|
||||
return ResourceManager.GetString("Green_value", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Hex value.
|
||||
/// </summary>
|
||||
public static string Hex_value {
|
||||
get {
|
||||
return ResourceManager.GetString("Hex_value", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Hue slider.
|
||||
/// </summary>
|
||||
public static string Hue_slider {
|
||||
get {
|
||||
return ResourceManager.GetString("Hue_slider", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Press the Color Picker icon to capture a color from your screen..
|
||||
/// </summary>
|
||||
public static string No_colors_yet {
|
||||
get {
|
||||
return ResourceManager.GetString("No_colors_yet", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to OK.
|
||||
/// </summary>
|
||||
public static string OK {
|
||||
get {
|
||||
return ResourceManager.GetString("OK", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Open settings.
|
||||
/// </summary>
|
||||
public static string Open_settings {
|
||||
get {
|
||||
return ResourceManager.GetString("Open_settings", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Pick color from screen.
|
||||
/// </summary>
|
||||
public static string Pick_color {
|
||||
get {
|
||||
return ResourceManager.GetString("Pick_color", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Red value.
|
||||
/// </summary>
|
||||
public static string Red_value {
|
||||
get {
|
||||
return ResourceManager.GetString("Red_value", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Remove.
|
||||
/// </summary>
|
||||
public static string Remove {
|
||||
get {
|
||||
return ResourceManager.GetString("Remove", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Saturation slider.
|
||||
/// </summary>
|
||||
public static string Saturation_slider {
|
||||
get {
|
||||
return ResourceManager.GetString("Saturation_slider", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Selected color.
|
||||
/// </summary>
|
||||
public static string Selected_color {
|
||||
get {
|
||||
return ResourceManager.GetString("Selected_color", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to This color can be adjusted.
|
||||
/// </summary>
|
||||
public static string Selected_color_helptext {
|
||||
get {
|
||||
return ResourceManager.GetString("Selected_color_helptext", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Adjust color.
|
||||
/// </summary>
|
||||
public static string Selected_color_tooltip {
|
||||
get {
|
||||
return ResourceManager.GetString("Selected_color_tooltip", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Value slider.
|
||||
/// </summary>
|
||||
public static string Value_slider {
|
||||
get {
|
||||
return ResourceManager.GetString("Value_slider", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
@ -60,6 +60,7 @@
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
@ -68,9 +69,10 @@
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
@ -85,9 +87,10 @@
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
@ -109,9 +112,85 @@
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Blue_value" xml:space="preserve">
|
||||
<value>Blue value</value>
|
||||
<comment>Tool tip that appears when hovering over a textbox that represents the blue HEX value</comment>
|
||||
</data>
|
||||
<data name="Cancel" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
<comment>Cancel button content</comment>
|
||||
</data>
|
||||
<data name="Copied_to_clipboard" xml:space="preserve">
|
||||
<value>Copied to clipboard</value>
|
||||
<comment>Message that appears when a user clicked a button that copies the value to the user's clipboard</comment>
|
||||
</data>
|
||||
<data name="Copy_to_clipboard" xml:space="preserve">
|
||||
<value>Copy to clipboard</value>
|
||||
<comment>Tooltip that describes a button that will copy a value to the user's clipboard</comment>
|
||||
</data>
|
||||
<data name="cp_editor" xml:space="preserve">
|
||||
<value>Color Picker editor</value>
|
||||
<comment>Do not translate product name</comment>
|
||||
</data>
|
||||
<data name="Green_value" xml:space="preserve">
|
||||
<value>Green value</value>
|
||||
<comment>Tool tip that appears when hovering over a textbox that represents the green HEX value</comment>
|
||||
</data>
|
||||
<data name="Hex_value" xml:space="preserve">
|
||||
<value>Hex value</value>
|
||||
<comment>Tool tip that appears when hovering over a textbox that represents the HEX value</comment>
|
||||
</data>
|
||||
<data name="Hue_slider" xml:space="preserve">
|
||||
<value>Hue slider</value>
|
||||
<comment>Tool tip that appears when hovering over a slider that represents the color hue (from HSV)</comment>
|
||||
</data>
|
||||
<data name="No_colors_yet" xml:space="preserve">
|
||||
<value>Press the Color Picker icon to capture a color from your screen.</value>
|
||||
<comment>Message that shows when the user launches the window for the first time or when no colors have been selected</comment>
|
||||
</data>
|
||||
<data name="OK" xml:space="preserve">
|
||||
<value>OK</value>
|
||||
<comment>OK button content</comment>
|
||||
</data>
|
||||
<data name="Open_settings" xml:space="preserve">
|
||||
<value>Open settings</value>
|
||||
<comment>Tooltip that shows that the user can click this button to open PowerToys settings</comment>
|
||||
</data>
|
||||
<data name="Pick_color" xml:space="preserve">
|
||||
<value>Pick color from screen</value>
|
||||
<comment>Tooltip that shows that the user can click this button to pick a new color</comment>
|
||||
</data>
|
||||
<data name="Red_value" xml:space="preserve">
|
||||
<value>Red value</value>
|
||||
<comment>Tool tip that appears when hovering over a textbox that represents the red HEX value</comment>
|
||||
</data>
|
||||
<data name="Remove" xml:space="preserve">
|
||||
<value>Remove</value>
|
||||
<comment>Tooltip that shows that the user can remove an item from a list</comment>
|
||||
</data>
|
||||
<data name="Saturation_slider" xml:space="preserve">
|
||||
<value>Saturation slider</value>
|
||||
<comment>Tool tip that appears when hovering over a slider that represents the color saturation (from HSV)</comment>
|
||||
</data>
|
||||
<data name="Selected_color" xml:space="preserve">
|
||||
<value>Selected color</value>
|
||||
<comment>Tooltip that shows the user what the selected color is</comment>
|
||||
</data>
|
||||
<data name="Selected_color_helptext" xml:space="preserve">
|
||||
<value>This color can be adjusted</value>
|
||||
<comment>Narrator message that describes to the user that this color can be adjusted</comment>
|
||||
</data>
|
||||
<data name="Selected_color_tooltip" xml:space="preserve">
|
||||
<value>Adjust color</value>
|
||||
<comment>Tooltip that shows that the user can adjust this color</comment>
|
||||
</data>
|
||||
<data name="Value_slider" xml:space="preserve">
|
||||
<value>Value slider</value>
|
||||
<comment>Tool tip that appears when hovering over a slider that represents the color value (from HSV)</comment>
|
||||
</data>
|
||||
</root>
|
@ -1,5 +1,133 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
xmlns:converters="clr-namespace:ColorPicker.Converters">
|
||||
<!--CONVERTERS-->
|
||||
<BooleanToVisibilityConverter x:Key="bool2VisibilityConverter" />
|
||||
<converters:ColorToBrushConverter x:Key="colorToBrushConverter"/>
|
||||
<converters:ColorToStringConverter x:Key="colorToStringConverter"/>
|
||||
<converters:NumberToVisibilityConverter x:Key="numberToVisibilityConverter"/>
|
||||
<converters:NumberToInvertedVisibilityConverter x:Key="numberToInvertedVisibilityConverter"/>
|
||||
|
||||
<Style x:Key="ColorHistoryListViewStyle" TargetType="{x:Type ListBoxItem}">
|
||||
<Setter Property="SnapsToDevicePixels" Value="True"/>
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}"/>
|
||||
<Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type ItemsControl}}}"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="BorderBrush" Value="Transparent"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="FocusVisualStyle">
|
||||
<Setter.Value>
|
||||
<Style>
|
||||
<Setter Property="Control.Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate>
|
||||
<Rectangle Margin="2" SnapsToDevicePixels="True" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ListBoxItem}">
|
||||
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">
|
||||
<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsMouseOver" Value="True"/>
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource ListViewPointerOverBrush}"/>
|
||||
</MultiTrigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="Selector.IsSelectionActive" Value="False"/>
|
||||
<Condition Property="IsSelected" Value="True"/>
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource ListViewPressedBrush}"/>
|
||||
</MultiTrigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="Selector.IsSelectionActive" Value="True"/>
|
||||
<Condition Property="IsSelected" Value="True"/>
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource ListViewPressedBrush}"/>
|
||||
</MultiTrigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="ColorShadeButtonStyle" TargetType="Button">
|
||||
<Setter Property="OverridesDefaultStyle" Value="True" />
|
||||
<Setter Property="Background" Value="{DynamicResource ButtonBackground}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource ButtonForeground}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrush}" />
|
||||
<Setter Property="BorderThickness" Value="{DynamicResource ButtonBorderThemeThickness}" />
|
||||
<Setter Property="Padding" Value="8,5,8,6" />
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="FontFamily" Value="{DynamicResource ContentControlThemeFontFamily}" />
|
||||
<Setter Property="FontWeight" Value="Normal" />
|
||||
<Setter Property="FontSize" Value="{DynamicResource ControlContentThemeFontSize}" />
|
||||
<Setter Property="FocusVisualStyle" Value="{DynamicResource {x:Static SystemParameters.FocusVisualStyleKey}}" />
|
||||
<Setter Property="ui:FocusVisualHelper.UseSystemFocusVisuals" Value="{DynamicResource UseSystemFocusVisuals}" />
|
||||
<Setter Property="ui:FocusVisualHelper.FocusVisualMargin" Value="-3" />
|
||||
<Setter Property="ui:ControlHelper.CornerRadius" Value="{DynamicResource ControlCornerRadius}" />
|
||||
<Setter Property="Stylus.IsPressAndHoldEnabled" Value="False" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border
|
||||
x:Name="Background"
|
||||
Background="{TemplateBinding Background}"
|
||||
CornerRadius="{TemplateBinding ui:ControlHelper.CornerRadius}"
|
||||
SnapsToDevicePixels="True">
|
||||
<Border
|
||||
x:Name="Border"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
CornerRadius="{TemplateBinding ui:ControlHelper.CornerRadius}">
|
||||
<ContentPresenter
|
||||
x:Name="ContentPresenter"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Focusable="False"
|
||||
RecognizesAccessKey="True"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
</Border>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="Background" Property="Opacity" Value="0.8" />
|
||||
<Setter TargetName="Border" Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushPointerOver}" />
|
||||
<Setter TargetName="ContentPresenter" Property="TextElement.Foreground" Value="{DynamicResource ButtonForegroundPointerOver}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter TargetName="Background" Property="Opacity" Value="0.9" />
|
||||
<Setter TargetName="Border" Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushPressed}" />
|
||||
<Setter TargetName="ContentPresenter" Property="TextElement.Foreground" Value="{DynamicResource ButtonForegroundPressed}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter TargetName="Background" Property="Background" Value="{DynamicResource ButtonBackgroundDisabled}" />
|
||||
<Setter TargetName="Border" Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushDisabled}" />
|
||||
<Setter TargetName="ContentPresenter" Property="TextElement.Foreground" Value="{DynamicResource ButtonForegroundDisabled}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
@ -9,4 +9,8 @@
|
||||
<DataTemplate DataType="{x:Type viewModels:ZoomViewModel}">
|
||||
<views:ZoomView/>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate DataType="{x:Type viewModels:ColorEditorViewModel}">
|
||||
<views:ColorEditorView/>
|
||||
</DataTemplate>
|
||||
</ResourceDictionary>
|
Binary file not shown.
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 122 KiB |
@ -2,6 +2,8 @@
|
||||
// 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.ObjectModel;
|
||||
using ColorPicker.Common;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
|
||||
|
||||
namespace ColorPicker.Settings
|
||||
@ -13,5 +15,13 @@ namespace ColorPicker.Settings
|
||||
SettingItem<bool> ChangeCursor { get; }
|
||||
|
||||
SettingItem<ColorRepresentationType> CopiedColorRepresentation { get; set; }
|
||||
|
||||
SettingItem<ColorPickerActivationAction> ActivationAction { get; }
|
||||
|
||||
RangeObservableCollection<string> ColorHistory { get; }
|
||||
|
||||
SettingItem<int> ColorHistoryLimit { get; }
|
||||
|
||||
ObservableCollection<string> VisibleColorFormats { get; }
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,13 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.IO.Abstractions;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using ColorPicker.Common;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
||||
@ -20,22 +23,40 @@ namespace ColorPicker.Settings
|
||||
private const string ColorPickerModuleName = "ColorPicker";
|
||||
private const string DefaultActivationShortcut = "Ctrl + Break";
|
||||
private const int MaxNumberOfRetry = 5;
|
||||
private const int SettingsReadOnChangeDelayInMs = 300;
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0052:Remove unread private members", Justification = "Actually, call back is LoadSettingsFromJson")]
|
||||
private readonly IFileSystemWatcher _watcher;
|
||||
|
||||
private readonly object _loadingSettingsLock = new object();
|
||||
|
||||
private bool _loadingColorsHistory;
|
||||
|
||||
[ImportingConstructor]
|
||||
public UserSettings()
|
||||
public UserSettings(Helpers.IThrottledActionInvoker throttledActionInvoker)
|
||||
{
|
||||
_settingsUtils = new SettingsUtils();
|
||||
ChangeCursor = new SettingItem<bool>(true);
|
||||
ActivationShortcut = new SettingItem<string>(DefaultActivationShortcut);
|
||||
CopiedColorRepresentation = new SettingItem<ColorRepresentationType>(ColorRepresentationType.HEX);
|
||||
ActivationAction = new SettingItem<ColorPickerActivationAction>(ColorPickerActivationAction.OpenEditor);
|
||||
ColorHistoryLimit = new SettingItem<int>(20);
|
||||
ColorHistory.CollectionChanged += ColorHistory_CollectionChanged;
|
||||
|
||||
LoadSettingsFromJson();
|
||||
_watcher = Helper.GetFileWatcher(ColorPickerModuleName, "settings.json", LoadSettingsFromJson);
|
||||
|
||||
// delay loading settings on change by some time to avoid file in use exception
|
||||
_watcher = Helper.GetFileWatcher(ColorPickerModuleName, "settings.json", () => throttledActionInvoker.ScheduleAction(LoadSettingsFromJson, SettingsReadOnChangeDelayInMs));
|
||||
}
|
||||
|
||||
private void ColorHistory_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (!_loadingColorsHistory)
|
||||
{
|
||||
var settings = _settingsUtils.GetSettings<ColorPickerSettings>(ColorPickerModuleName);
|
||||
settings.Properties.ColorHistory = ColorHistory.ToList();
|
||||
settings.Save(_settingsUtils);
|
||||
}
|
||||
}
|
||||
|
||||
public SettingItem<string> ActivationShortcut { get; private set; }
|
||||
@ -44,6 +65,14 @@ namespace ColorPicker.Settings
|
||||
|
||||
public SettingItem<ColorRepresentationType> CopiedColorRepresentation { get; set; }
|
||||
|
||||
public SettingItem<ColorPickerActivationAction> ActivationAction { get; private set; }
|
||||
|
||||
public RangeObservableCollection<string> ColorHistory { get; private set; } = new RangeObservableCollection<string>();
|
||||
|
||||
public SettingItem<int> ColorHistoryLimit { get; }
|
||||
|
||||
public ObservableCollection<string> VisibleColorFormats { get; private set; } = new ObservableCollection<string>();
|
||||
|
||||
private void LoadSettingsFromJson()
|
||||
{
|
||||
// TODO this IO call should by Async, update GetFileWatcher helper to support async
|
||||
@ -72,6 +101,31 @@ namespace ColorPicker.Settings
|
||||
ChangeCursor.Value = settings.Properties.ChangeCursor;
|
||||
ActivationShortcut.Value = settings.Properties.ActivationShortcut.ToString();
|
||||
CopiedColorRepresentation.Value = settings.Properties.CopiedColorRepresentation;
|
||||
ActivationAction.Value = settings.Properties.ActivationAction;
|
||||
ColorHistoryLimit.Value = settings.Properties.ColorHistoryLimit;
|
||||
|
||||
if (settings.Properties.ColorHistory == null)
|
||||
{
|
||||
settings.Properties.ColorHistory = new System.Collections.Generic.List<string>();
|
||||
}
|
||||
|
||||
_loadingColorsHistory = true;
|
||||
ColorHistory.Clear();
|
||||
foreach (var item in settings.Properties.ColorHistory)
|
||||
{
|
||||
ColorHistory.Add(item);
|
||||
}
|
||||
|
||||
_loadingColorsHistory = false;
|
||||
|
||||
VisibleColorFormats.Clear();
|
||||
foreach (var item in settings.Properties.VisibleColorFormats)
|
||||
{
|
||||
if (item.Value)
|
||||
{
|
||||
VisibleColorFormats.Add(item.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retry = false;
|
||||
|
201
src/modules/colorPicker/ColorPickerUI/ThemeManager.cs
Normal file
201
src/modules/colorPicker/ColorPickerUI/ThemeManager.cs
Normal 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 ColorPicker.Helpers;
|
||||
using ControlzEx.Theming;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace ColorPicker
|
||||
{
|
||||
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,
|
||||
}
|
||||
}
|
24
src/modules/colorPicker/ColorPickerUI/Themes/Dark.xaml
Normal file
24
src/modules/colorPicker/ColorPickerUI/Themes/Dark.xaml
Normal file
@ -0,0 +1,24 @@
|
||||
<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">PowerToysRun</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="WindowBorderBrush" Color="#FF535353"/>
|
||||
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF9a9a9a"/>
|
||||
|
||||
<SolidColorBrush x:Key="ListViewPointerOverBrush" Color="#FF242424"/>
|
||||
<SolidColorBrush x:Key="ListViewPressedBrush" Color="#FF333333"/>
|
||||
|
||||
<SolidColorBrush x:Key="ColorControlBackgroundBrush" Color="#FF454545"/>
|
||||
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FFFFFFFF" />
|
||||
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF6b6b6b" />
|
||||
</ResourceDictionary>
|
@ -0,0 +1,24 @@
|
||||
<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">PowerToysRun</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="WindowBorderBrush" Color="#FFffff00"/>
|
||||
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF9a9a9a"/>
|
||||
|
||||
<SolidColorBrush x:Key="ListViewPointerOverBrush" Color="#FF242424"/>
|
||||
<SolidColorBrush x:Key="ListViewPressedBrush" Color="#FF333333"/>
|
||||
|
||||
<SolidColorBrush x:Key="ColorControlBackgroundBrush" Color="#FF454545"/>
|
||||
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FFffff00" />
|
||||
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF00ff00" />
|
||||
</ResourceDictionary>
|
@ -0,0 +1,25 @@
|
||||
<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">PowerToysRun</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="WindowBorderBrush" Color="#FF00ff00"/>
|
||||
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF9a9a9a"/>
|
||||
|
||||
<SolidColorBrush x:Key="ListViewPointerOverBrush" Color="#FF242424"/>
|
||||
<SolidColorBrush x:Key="ListViewPressedBrush" Color="#FF333333"/>
|
||||
|
||||
<SolidColorBrush x:Key="ColorControlBackgroundBrush" Color="#FF454545"/>
|
||||
|
||||
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FF00ff00" />
|
||||
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FFc0c0c0" />
|
||||
</ResourceDictionary>
|
@ -0,0 +1,25 @@
|
||||
<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">PowerToysRun</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="WindowBorderBrush" Color="#FFffffff"/>
|
||||
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF9a9a9a"/>
|
||||
|
||||
<SolidColorBrush x:Key="ListViewPointerOverBrush" Color="#FF242424"/>
|
||||
<SolidColorBrush x:Key="ListViewPressedBrush" Color="#FF333333"/>
|
||||
|
||||
<SolidColorBrush x:Key="ColorControlBackgroundBrush" Color="#FF454545"/>
|
||||
|
||||
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FFffffff" />
|
||||
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF1aebff" />
|
||||
</ResourceDictionary>
|
@ -0,0 +1,25 @@
|
||||
<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">PowerToysRun</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="#FFededed" />
|
||||
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FFe5e5e5" />
|
||||
<SolidColorBrush x:Key="WindowBorderBrush" Color="Black"/>
|
||||
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF949494"/>
|
||||
|
||||
<SolidColorBrush x:Key="ListViewPointerOverBrush" Color="#e9e9e9"/>
|
||||
<SolidColorBrush x:Key="ListViewPressedBrush" Color="#FFe5e5e5"/>
|
||||
|
||||
<SolidColorBrush x:Key="ColorControlBackgroundBrush" Color="#FFf9f9f9"/>
|
||||
|
||||
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FF000000" />
|
||||
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF37006e" />
|
||||
</ResourceDictionary>
|
25
src/modules/colorPicker/ColorPickerUI/Themes/Light.xaml
Normal file
25
src/modules/colorPicker/ColorPickerUI/Themes/Light.xaml
Normal file
@ -0,0 +1,25 @@
|
||||
<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">PowerToysRun</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="#FFededed" />
|
||||
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FFe5e5e5" />
|
||||
<SolidColorBrush x:Key="WindowBorderBrush" Color="#FFf7f7f7"/>
|
||||
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF949494"/>
|
||||
|
||||
<SolidColorBrush x:Key="ListViewPointerOverBrush" Color="#e9e9e9"/>
|
||||
<SolidColorBrush x:Key="ListViewPressedBrush" Color="#FFe5e5e5"/>
|
||||
|
||||
<SolidColorBrush x:Key="ColorControlBackgroundBrush" Color="#FFf9f9f9"/>
|
||||
|
||||
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FF000000" />
|
||||
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF949494" />
|
||||
</ResourceDictionary>
|
@ -0,0 +1,31 @@
|
||||
// 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.Collections.ObjectModel;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using ColorPicker.Models;
|
||||
|
||||
namespace ColorPicker.ViewModelContracts
|
||||
{
|
||||
public interface IColorEditorViewModel
|
||||
{
|
||||
event EventHandler OpenColorPickerRequested;
|
||||
|
||||
ICommand OpenColorPickerCommand { get; }
|
||||
|
||||
ICommand RemoveColorCommand { get; }
|
||||
|
||||
ObservableCollection<ColorFormatModel> ColorRepresentations { get; }
|
||||
|
||||
ObservableCollection<Color> ColorsHistory { get; }
|
||||
|
||||
Color SelectedColor { get; set; }
|
||||
|
||||
int SelectedColorIndex { get; set; }
|
||||
|
||||
void Initialize();
|
||||
}
|
||||
}
|
@ -0,0 +1,224 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using ColorPicker.Common;
|
||||
using ColorPicker.Helpers;
|
||||
using ColorPicker.Models;
|
||||
using ColorPicker.Settings;
|
||||
using ColorPicker.ViewModelContracts;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
|
||||
|
||||
namespace ColorPicker.ViewModels
|
||||
{
|
||||
[Export(typeof(IColorEditorViewModel))]
|
||||
public class ColorEditorViewModel : ViewModelBase, IColorEditorViewModel
|
||||
{
|
||||
private readonly IUserSettings _userSettings;
|
||||
private readonly List<ColorFormatModel> _allColorRepresentations = new List<ColorFormatModel>();
|
||||
private Color _selectedColor;
|
||||
private bool _initializing;
|
||||
private int _selectedColorIndex;
|
||||
|
||||
[ImportingConstructor]
|
||||
public ColorEditorViewModel(IUserSettings userSettings)
|
||||
{
|
||||
OpenColorPickerCommand = new RelayCommand(() => OpenColorPickerRequested?.Invoke(this, EventArgs.Empty));
|
||||
RemoveColorCommand = new RelayCommand(DeleteSelectedColor);
|
||||
|
||||
SelectedColorChangedCommand = new RelayCommand((newColor) =>
|
||||
{
|
||||
ColorsHistory.Insert(0, (Color)newColor);
|
||||
SelectedColorIndex = 0;
|
||||
});
|
||||
ColorsHistory.CollectionChanged += ColorsHistory_CollectionChanged;
|
||||
_userSettings = userSettings;
|
||||
SetupAllColorRepresentations();
|
||||
SetupAvailableColorRepresentations();
|
||||
}
|
||||
|
||||
public event EventHandler OpenColorPickerRequested;
|
||||
|
||||
public ICommand OpenColorPickerCommand { get; }
|
||||
|
||||
public ICommand RemoveColorCommand { get; }
|
||||
|
||||
public ICommand SelectedColorChangedCommand { get; }
|
||||
|
||||
public ICommand HideColorFormatCommand { get; }
|
||||
|
||||
public ObservableCollection<Color> ColorsHistory { get; } = new ObservableCollection<Color>();
|
||||
|
||||
public ObservableCollection<ColorFormatModel> ColorRepresentations { get; } = new ObservableCollection<ColorFormatModel>();
|
||||
|
||||
public Color SelectedColor
|
||||
{
|
||||
get
|
||||
{
|
||||
return _selectedColor;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_selectedColor = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public int SelectedColorIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
return _selectedColorIndex;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_selectedColorIndex = value;
|
||||
if (value >= 0)
|
||||
{
|
||||
SelectedColor = ColorsHistory[_selectedColorIndex];
|
||||
}
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_initializing = true;
|
||||
|
||||
ColorsHistory.Clear();
|
||||
|
||||
foreach (var item in _userSettings.ColorHistory)
|
||||
{
|
||||
var parts = item.Split('|');
|
||||
ColorsHistory.Add(new Color()
|
||||
{
|
||||
A = byte.Parse(parts[0], NumberStyles.Integer, CultureInfo.InvariantCulture),
|
||||
R = byte.Parse(parts[1], NumberStyles.Integer, CultureInfo.InvariantCulture),
|
||||
G = byte.Parse(parts[2], NumberStyles.Integer, CultureInfo.InvariantCulture),
|
||||
B = byte.Parse(parts[3], NumberStyles.Integer, CultureInfo.InvariantCulture),
|
||||
});
|
||||
SelectedColorIndex = 0;
|
||||
}
|
||||
|
||||
_initializing = false;
|
||||
}
|
||||
|
||||
private void ColorsHistory_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (!_initializing)
|
||||
{
|
||||
_userSettings.ColorHistory.ClearWithoutNotification();
|
||||
foreach (var item in ColorsHistory)
|
||||
{
|
||||
_userSettings.ColorHistory.AddWithoutNotification(item.A + "|" + item.R + "|" + item.G + "|" + item.B);
|
||||
}
|
||||
|
||||
_userSettings.ColorHistory.ReleaseNotification();
|
||||
}
|
||||
}
|
||||
|
||||
private void DeleteSelectedColor()
|
||||
{
|
||||
// select new color on the same index if possible, otherwise the last one
|
||||
var indexToSelect = SelectedColorIndex == ColorsHistory.Count - 1 ? ColorsHistory.Count - 2 : SelectedColorIndex;
|
||||
ColorsHistory.RemoveAt(SelectedColorIndex);
|
||||
SelectedColorIndex = indexToSelect;
|
||||
}
|
||||
|
||||
private void SetupAllColorRepresentations()
|
||||
{
|
||||
_allColorRepresentations.Add(
|
||||
new ColorFormatModel()
|
||||
{
|
||||
FormatName = ColorRepresentationType.HEX.ToString(),
|
||||
Convert = (Color color) => { return ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.HEX); },
|
||||
});
|
||||
|
||||
_allColorRepresentations.Add(
|
||||
new ColorFormatModel()
|
||||
{
|
||||
FormatName = ColorRepresentationType.RGB.ToString(),
|
||||
Convert = (Color color) => { return ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.RGB); },
|
||||
});
|
||||
|
||||
_allColorRepresentations.Add(
|
||||
new ColorFormatModel()
|
||||
{
|
||||
FormatName = ColorRepresentationType.HSL.ToString(),
|
||||
Convert = (Color color) => { return ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.HSL); },
|
||||
});
|
||||
|
||||
_allColorRepresentations.Add(
|
||||
new ColorFormatModel()
|
||||
{
|
||||
FormatName = ColorRepresentationType.HSV.ToString(),
|
||||
Convert = (Color color) => { return ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.HSV); },
|
||||
});
|
||||
|
||||
_allColorRepresentations.Add(
|
||||
new ColorFormatModel()
|
||||
{
|
||||
FormatName = ColorRepresentationType.CMYK.ToString(),
|
||||
Convert = (Color color) => { return ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.CMYK); },
|
||||
});
|
||||
_allColorRepresentations.Add(
|
||||
new ColorFormatModel()
|
||||
{
|
||||
FormatName = ColorRepresentationType.HSB.ToString(),
|
||||
Convert = (Color color) => { return ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.HSB); },
|
||||
});
|
||||
_allColorRepresentations.Add(
|
||||
new ColorFormatModel()
|
||||
{
|
||||
FormatName = ColorRepresentationType.HSI.ToString(),
|
||||
Convert = (Color color) => { return ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.HSI); },
|
||||
});
|
||||
_allColorRepresentations.Add(
|
||||
new ColorFormatModel()
|
||||
{
|
||||
FormatName = ColorRepresentationType.HWB.ToString(),
|
||||
Convert = (Color color) => { return ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.HWB); },
|
||||
});
|
||||
_allColorRepresentations.Add(
|
||||
new ColorFormatModel()
|
||||
{
|
||||
FormatName = ColorRepresentationType.NCol.ToString(),
|
||||
Convert = (Color color) => { return ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.NCol); },
|
||||
});
|
||||
|
||||
_userSettings.VisibleColorFormats.CollectionChanged += VisibleColorFormats_CollectionChanged;
|
||||
|
||||
// Any other custom format to be added here as well that are read from settings
|
||||
}
|
||||
|
||||
private void VisibleColorFormats_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
SetupAvailableColorRepresentations();
|
||||
}
|
||||
|
||||
private void SetupAvailableColorRepresentations()
|
||||
{
|
||||
ColorRepresentations.Clear();
|
||||
|
||||
foreach (var colorFormat in _userSettings.VisibleColorFormats)
|
||||
{
|
||||
var colorRepresentation = _allColorRepresentations.FirstOrDefault(it => it.FormatName.ToUpperInvariant() == colorFormat.ToUpperInvariant());
|
||||
if (colorRepresentation != null)
|
||||
{
|
||||
ColorRepresentations.Add(colorRepresentation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ using ColorPicker.Mouse;
|
||||
using ColorPicker.Settings;
|
||||
using ColorPicker.Telemetry;
|
||||
using ColorPicker.ViewModelContracts;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
|
||||
namespace ColorPicker.ViewModels
|
||||
@ -22,11 +23,6 @@ namespace ColorPicker.ViewModels
|
||||
[Export(typeof(IMainViewModel))]
|
||||
public class MainViewModel : ViewModelBase, IMainViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Defined error code for "clipboard can't open"
|
||||
/// </summary>
|
||||
private const uint ErrorCodeClipboardCantOpen = 0x800401D0;
|
||||
|
||||
private readonly ZoomWindowHelper _zoomWindowHelper;
|
||||
private readonly AppStateHandler _appStateHandler;
|
||||
private readonly IUserSettings _userSettings;
|
||||
@ -107,41 +103,29 @@ namespace ColorPicker.ViewModels
|
||||
/// <param name="p">The current <see cref="System.Drawing.Point"/> of the mouse cursor</param>
|
||||
private void MouseInfoProvider_OnMouseDown(object sender, System.Drawing.Point p)
|
||||
{
|
||||
CopyToClipboard(ColorText);
|
||||
ClipboardHelper.CopyToClipboard(ColorText);
|
||||
|
||||
_userSettings.ColorHistory.Insert(0, GetColorString());
|
||||
|
||||
if (_userSettings.ColorHistory.Count > _userSettings.ColorHistoryLimit.Value)
|
||||
{
|
||||
_userSettings.ColorHistory.RemoveAt(_userSettings.ColorHistory.Count - 1);
|
||||
}
|
||||
|
||||
_appStateHandler.HideColorPicker();
|
||||
|
||||
if (_userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenColorPickerAndThenEditor || _userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenEditor)
|
||||
{
|
||||
_appStateHandler.ShowColorPickerEditor();
|
||||
}
|
||||
|
||||
PowerToysTelemetry.Log.WriteEvent(new ColorPickerShowEvent());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy the given text to the Windows clipboard
|
||||
/// </summary>
|
||||
/// <param name="text">The text to copy to the Windows clipboard</param>
|
||||
private static void CopyToClipboard(string text)
|
||||
private string GetColorString()
|
||||
{
|
||||
if (string.IsNullOrEmpty(text))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// nasty hack - sometimes clipboard can be in use and it will raise and exception
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
Clipboard.SetText(text);
|
||||
break;
|
||||
}
|
||||
catch (COMException ex)
|
||||
{
|
||||
if ((uint)ex.ErrorCode != ErrorCodeClipboardCantOpen)
|
||||
{
|
||||
Logger.LogError("Failed to set text into clipboard", ex);
|
||||
}
|
||||
}
|
||||
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
var color = ((SolidColorBrush)ColorBrush).Color;
|
||||
return color.A + "|" + color.R + "|" + color.G + "|" + color.B;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
167
src/modules/colorPicker/ColorPickerUI/Views/ColorEditorView.xaml
Normal file
167
src/modules/colorPicker/ColorPickerUI/Views/ColorEditorView.xaml
Normal file
@ -0,0 +1,167 @@
|
||||
<UserControl x:Class="ColorPicker.Views.ColorEditorView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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:p="clr-namespace:ColorPicker.Properties"
|
||||
mc:Ignorable="d"
|
||||
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
xmlns:e="http://schemas.microsoft.com/expression/2010/interactivity"
|
||||
xmlns:controls="clr-namespace:ColorPicker.Controls"
|
||||
xmlns:behaviors="clr-namespace:ColorPicker.Behaviors"
|
||||
WindowChrome.IsHitTestVisibleInChrome="True"
|
||||
x:Name="colorEditorControl">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="64"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Side bar -->
|
||||
<Grid Background="{DynamicResource SecondaryBackgroundBrush}">
|
||||
<ui:ListView Margin="0,48,0,0"
|
||||
Grid.Row="1"
|
||||
Padding="0"
|
||||
TabIndex="3"
|
||||
ItemsSource="{Binding ColorsHistory}"
|
||||
SelectedIndex="{Binding SelectedColorIndex}"
|
||||
ItemContainerStyle="{DynamicResource ColorHistoryListViewStyle}">
|
||||
<ui:ListView.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="{x:Static p:Resources.Remove}"
|
||||
Command="{Binding RemoveColorCommand}">
|
||||
<MenuItem.Icon>
|
||||
<ui:FontIcon Glyph="" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</ui:ListView.ContextMenu>
|
||||
<ui:ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Width="64" Height="48">
|
||||
<Border
|
||||
Width="26"
|
||||
Height="26"
|
||||
CornerRadius="4"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Background="{Binding Path=., Converter={StaticResource colorToBrushConverter}}">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect BlurRadius="6" Opacity="0.32" ShadowDepth="2" />
|
||||
</Border.Effect>
|
||||
</Border>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ui:ListView.ItemTemplate>
|
||||
</ui:ListView>
|
||||
</Grid>
|
||||
|
||||
<!-- Title bar -->
|
||||
<Grid Grid.ColumnSpan="2"
|
||||
Height="32"
|
||||
Background="Transparent"
|
||||
VerticalAlignment="Top"
|
||||
IsHitTestVisible="True">
|
||||
<e:Interaction.Behaviors>
|
||||
<behaviors:DragWindowBehavior/>
|
||||
</e:Interaction.Behaviors>
|
||||
<Border
|
||||
Background="{DynamicResource TitleBarSecondaryForegroundBrush}"
|
||||
Grid.ColumnSpan="2"
|
||||
Width="30"
|
||||
Height="3"
|
||||
CornerRadius="1.5"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0,1,0,0" />
|
||||
|
||||
<!-- Enable once we have settings linking available -->
|
||||
<!--<Button Width="46"
|
||||
Height="32"
|
||||
Content=""
|
||||
TabIndex="2"
|
||||
Background="Transparent"
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
HorizontalAlignment="Right"
|
||||
Margin="0,0,46,0"
|
||||
ToolTipService.ToolTip="{x:Static p:Resources.Open_settings}"
|
||||
AutomationProperties.Name="{x:Static p:Resources.Open_settings}" />-->
|
||||
|
||||
<Button Width="64"
|
||||
Height="32"
|
||||
TabIndex="1"
|
||||
Content=""
|
||||
Command="{Binding OpenColorPickerCommand}"
|
||||
Background="Transparent"
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
ToolTipService.ToolTip="{x:Static p:Resources.Pick_color}"
|
||||
AutomationProperties.Name="{x:Static p:Resources.Pick_color}"/>
|
||||
</Grid>
|
||||
|
||||
<!-- Main grid -->
|
||||
<Grid Grid.Column="1" Visibility="{Binding ColorsHistory.Count, Converter={StaticResource numberToVisibilityConverter}}">
|
||||
<ScrollViewer Grid.Column="1" Margin="0,90,0,0">
|
||||
<StackPanel>
|
||||
<ItemsControl ItemsSource="{Binding ColorRepresentations}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<controls:ColorFormatControl
|
||||
ColorFormatModel="{Binding }"
|
||||
SelectedColor="{Binding ElementName=colorEditorControl, Path=DataContext.SelectedColor}"
|
||||
ColorCopiedNotificationBorder="{Binding ElementName=CopiedBorderIndicator}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel
|
||||
Orientation="Vertical"
|
||||
Margin="0,16,0,16"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
<controls:ColorPickerControl
|
||||
HorizontalAlignment="Left"
|
||||
Margin="0,44,0,0"
|
||||
SelectedColor="{Binding SelectedColor}"
|
||||
SelectedColorChangedCommand="{Binding SelectedColorChangedCommand}"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Top"/>
|
||||
</Grid>
|
||||
|
||||
<!-- Empty history -->
|
||||
<StackPanel Grid.Column="1" Margin="12" VerticalAlignment="Center" Orientation="Vertical" Visibility="{Binding ColorsHistory.Count, Converter={StaticResource numberToInvertedVisibilityConverter}}">
|
||||
<TextBlock Text=""
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
FontSize="44"
|
||||
HorizontalAlignment="Center"
|
||||
Foreground="{DynamicResource SecondaryForegroundBrush}" />
|
||||
<TextBlock Margin="0,16,0,0"
|
||||
TextWrapping="Wrap"
|
||||
TextAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
Foreground="{DynamicResource SecondaryForegroundBrush}"
|
||||
Text="{x:Static p:Resources.No_colors_yet}"/>
|
||||
</StackPanel>
|
||||
|
||||
<Border x:Name="CopiedBorderIndicator"
|
||||
Opacity="0"
|
||||
Grid.ColumnSpan="2"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Bottom"
|
||||
Height="0"
|
||||
Background="{DynamicResource SystemControlBackgroundAccentBrush}">
|
||||
|
||||
<TextBlock FontSize="16"
|
||||
Foreground="White"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" >
|
||||
<Run Text=" " FontFamily="Segoe MDL2 Assets"/>
|
||||
<Run Text="{x:Static p:Resources.Copied_to_clipboard}" FontWeight="SemiBold"/>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
@ -0,0 +1,30 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace ColorPicker.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ColorEditorView.xaml
|
||||
/// </summary>
|
||||
public partial class ColorEditorView : UserControl
|
||||
{
|
||||
public ColorEditorView() =>
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
@ -1,55 +1,48 @@
|
||||
<UserControl x:Class="ColorPicker.Views.MainView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:ColorPicker.Views"
|
||||
xmlns:viewModel="clr-namespace:ColorPicker.ViewModels"
|
||||
xmlns:constants="clr-namespace:ColorPicker.Constants"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="50"
|
||||
d:DesignWidth="{x:Static constants:WindowConstant.PickerWindowWidth}"
|
||||
d:DataContext="{d:DesignInstance viewModel:MainViewModel, IsDesignTimeCreatable=True}" >
|
||||
mc:Ignorable="d" d:DesignHeight="64"
|
||||
d:DataContext="{d:DesignInstance viewModel:MainViewModel, IsDesignTimeCreatable=True}">
|
||||
<Grid Background="Transparent">
|
||||
|
||||
<Grid Background="Transparent" >
|
||||
<Grid>
|
||||
<Border BorderBrush="{DynamicResource WindowBorderBrush}"
|
||||
Margin="12"
|
||||
BorderThickness="1"
|
||||
Background="{DynamicResource PrimaryBackgroundBrush}"
|
||||
CornerRadius="4">
|
||||
<!-- Disabled due to the poor performance of drawing shadows in WPF -->
|
||||
<!--<Border.Effect>
|
||||
<DropShadowEffect
|
||||
BlurRadius="16"
|
||||
Opacity="0.28"
|
||||
ShadowDepth="1" />
|
||||
</Border.Effect>-->
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="20" />
|
||||
<ColumnDefinition Width="50" />
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid Margin="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="36"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Border Grid.Column="2"
|
||||
Margin="0,1,1,1"
|
||||
Background="#202020"
|
||||
BorderBrush="#505050"
|
||||
BorderThickness="3,0,3,0"
|
||||
CornerRadius="0" />
|
||||
|
||||
<Border Grid.Column="1"
|
||||
Background="{Binding ColorBrush}"
|
||||
BorderBrush="Black"
|
||||
<Border Background="{Binding ColorBrush}"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
BorderBrush="{DynamicResource WindowBorderBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="2,0,0,2" />
|
||||
x:Name="ColorBorder"
|
||||
CornerRadius="4"/>
|
||||
|
||||
<Border Grid.Column="1"
|
||||
Grid.ColumnSpan="2"
|
||||
Background="Transparent"
|
||||
BorderThickness="1"
|
||||
BorderBrush="Black"
|
||||
CornerRadius="2" />
|
||||
|
||||
<TextBlock Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
Margin="7,0,0,0"
|
||||
Foreground="White"
|
||||
Text="{Binding ColorText}" />
|
||||
|
||||
</Grid>
|
||||
<TextBlock Margin="8,5,8,8"
|
||||
FontSize="16"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
Grid.Column="1"
|
||||
Text="{Binding ColorText}"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
|
@ -1,39 +1,61 @@
|
||||
<UserControl x:Class="ColorPicker.Views.ZoomView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:e="http://schemas.microsoft.com/expression/2010/interactivity"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:behaviors="clr-namespace:ColorPicker.Behaviors"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
xmlns:shaders="clr-namespace:ColorPicker.Shaders"
|
||||
xmlns:e="http://schemas.microsoft.com/expression/2010/interactivity"
|
||||
xmlns:behaviors="clr-namespace:ColorPicker.Behaviors"
|
||||
Background="Transparent"
|
||||
Focusable="False"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
mc:Ignorable="d" >
|
||||
|
||||
<Border BorderBrush="#FF2B2B2B"
|
||||
BorderThickness="2"
|
||||
ClipToBounds="True"
|
||||
CornerRadius="2" >
|
||||
|
||||
<Image Source="{Binding ZoomArea}"
|
||||
Height="{Binding Height, Mode=TwoWay}"
|
||||
Width="{Binding Width, Mode=TwoWay}"
|
||||
RenderOptions.BitmapScalingMode="NearestNeighbor"
|
||||
Stretch="Fill" >
|
||||
|
||||
<e:Interaction.Behaviors>
|
||||
<behaviors:ResizeBehavior Width="{Binding DesiredWidth}" Height="{Binding DesiredHeight}" />
|
||||
<behaviors:GridEffectBehavior Effect="{Binding ElementName=gridEffect}" ZoomFactor="{Binding ZoomFactor}" />
|
||||
</e:Interaction.Behaviors>
|
||||
|
||||
<Image.Effect>
|
||||
<shaders:GridShaderEffect x:Name="gridEffect" />
|
||||
</Image.Effect>
|
||||
|
||||
</Image>
|
||||
Focusable="False">
|
||||
|
||||
<Border x:Name="WindowBorder"
|
||||
BorderBrush="{DynamicResource WindowBorderBrush}"
|
||||
Margin="12"
|
||||
BorderThickness="1"
|
||||
Background="{DynamicResource PrimaryBackgroundBrush}"
|
||||
CornerRadius="4">
|
||||
<!-- Disabled due to the poor performance of drawing shadows in WPF -->
|
||||
<!--<Border.Effect>
|
||||
<DropShadowEffect BlurRadius="16" Opacity="0.28" ShadowDepth="1" />
|
||||
</Border.Effect>-->
|
||||
<Grid>
|
||||
<Image Margin="3" Source="{Binding ZoomArea}"
|
||||
RenderOptions.BitmapScalingMode="NearestNeighbor"
|
||||
Stretch="Fill"
|
||||
Width="{Binding Width, Mode=TwoWay}"
|
||||
Height="{Binding Height, Mode=TwoWay}">
|
||||
<e:Interaction.Behaviors>
|
||||
<behaviors:ResizeBehavior Width="{Binding DesiredWidth}" Height="{Binding DesiredHeight}"/>
|
||||
<behaviors:GridEffectBehavior Effect="{Binding ElementName=gridEffect}" ZoomFactor="{Binding ZoomFactor}"/>
|
||||
</e:Interaction.Behaviors>
|
||||
<Image.Effect>
|
||||
<shaders:GridShaderEffect x:Name="gridEffect"/>
|
||||
</Image.Effect>
|
||||
</Image>
|
||||
|
||||
<!-- Non-functional close button -->
|
||||
<Border HorizontalAlignment="Right"
|
||||
Visibility="Collapsed"
|
||||
VerticalAlignment="Top"
|
||||
CornerRadius="0,4,0,4"
|
||||
Background="{DynamicResource PrimaryBackgroundBrush}">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Path=IsMouseOver, ElementName=WindowBorder}" Value="False">
|
||||
<Setter Property="Opacity" Value="0"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<Button Height="40"
|
||||
Width="40"
|
||||
Content=""
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
Background="Transparent"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
</UserControl>
|
||||
|
@ -3,11 +3,18 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:ColorPicker"
|
||||
xmlns:e="http://schemas.microsoft.com/expression/2010/interactivity"
|
||||
xmlns:behaviors="clr-namespace:ColorPicker.Behaviors"
|
||||
mc:Ignorable="d"
|
||||
Title="Zoom window" WindowStyle="None" SizeToContent="WidthAndHeight" Topmost="True" AllowsTransparency="True" Background="Transparent" ShowInTaskbar="False" ResizeMode="NoResize" Focusable="False">
|
||||
Title="Zoom window"
|
||||
WindowStyle="None"
|
||||
SizeToContent="WidthAndHeight"
|
||||
Topmost="True"
|
||||
AllowsTransparency="True"
|
||||
Background="Transparent"
|
||||
ShowInTaskbar="False"
|
||||
ResizeMode="NoResize"
|
||||
Focusable="False">
|
||||
<e:Interaction.Behaviors>
|
||||
<behaviors:CloseZoomWindowBehavior/>
|
||||
<behaviors:MoveWindowBehavior Left="{Binding DesiredLeft, Mode=TwoWay}" Top="{Binding DesiredTop}"/>
|
||||
|
@ -2,16 +2,20 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<RootNamespace>UnitTest_ColorPickerUI</RootNamespace>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Platforms>x64</Platforms>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<OutputType>Library</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<OutputPath>..\..\..\..\x64\Debug\modules\ColorPicker\UnitTest-ColorPickerUI\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<OutputPath>..\..\..\..\x64\Release\modules\ColorPicker\UnitTest-ColorPickerUI\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
@ -29,19 +33,5 @@
|
||||
<ProjectReference Include="..\..\..\core\Microsoft.PowerToys.Settings.UI.Library\Microsoft.PowerToys.Settings.UI.Library.csproj" />
|
||||
<ProjectReference Include="..\ColorPickerUI\ColorPickerUI.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\..\codeAnalysis\GlobalSuppressions.cs">
|
||||
<Link>GlobalSuppressions.cs</Link>
|
||||
</Compile>
|
||||
<AdditionalFiles Include="..\..\..\codeAnalysis\StyleCop.json">
|
||||
<Link>StyleCop.json</Link>
|
||||
</AdditionalFiles>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="StyleCop.Analyzers">
|
||||
<Version>1.1.118</Version>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
Loading…
Reference in New Issue
Block a user