New color picker module - integrated from github.com/martinchrzan/Col… (#4778)

* New color picker module - integrated from github.com/martinchrzan/ColorPicker

* Trying to fix build in github

* Replaced icon in the settings to use font icon instead of path icon

* Closing ColorPicker.exe when PowerToys process closed, added color picker project into runner dependencies, restoring cursors on exit, added ManagedCommon as a dependency into installer

* User/ryanbod/fix colorpicker release (#5046)

* Changing configuration to x64 instead of AnyCPU.   The previous configuration was preventing the ManagedCommon binary from being loaded in Release.

* Updating MSI Installer with new icons (#4998)

* Adding missed dll into installer

* Fixed potential exception

* Creating settings.json on the first start when there are none, fixed default keyboard shortcut

* Added ColorPicker.exe.config into installer

* Start filewatcher after default settings file is created

* Fixing build

Co-authored-by: ryanbodrug-microsoft <56318517+ryanbodrug-microsoft@users.noreply.github.com>
This commit is contained in:
martinchrzan
2020-07-18 21:27:36 +02:00
committed by GitHub
parent d09253e532
commit bc301f269a
72 changed files with 3654 additions and 6 deletions

View File

@@ -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.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Lib
{
public enum ColorRepresentationType
{
HEX = 0,
RGB = 1,
}
public class ColorPickerProperties
{
public ColorPickerProperties()
{
ActivationShortcut = new HotkeySettings(false, true, false, false, "Break", 3);
ChangeCursor = true;
}
public HotkeySettings ActivationShortcut { get; set; }
[JsonPropertyName("changecursor")]
[JsonConverter(typeof(BoolPropertyJsonConverter))]
public bool ChangeCursor { get; set; }
[JsonPropertyName("copiedcolorrepresentation")]
public ColorRepresentationType CopiedColorRepresentation { get; set; }
public override string ToString()
{
return JsonSerializer.Serialize(this);
}
}
}

View File

@@ -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.Text.Json;
namespace Microsoft.PowerToys.Settings.UI.Lib
{
public class ColorPickerSettings : BasePTModuleSettings
{
public const string ModuleName = "ColorPicker";
public ColorPickerProperties properties { get; set; }
public ColorPickerSettings()
{
properties = new ColorPickerProperties();
version = "1";
name = ModuleName;
}
public override string ToJsonString()
{
return JsonSerializer.Serialize(this);
}
public virtual void Save()
{
// Save settings to file
var options = new JsonSerializerOptions
{
WriteIndented = true,
};
SettingsUtils.SaveSettings(JsonSerializer.Serialize(this, options), ModuleName);
}
}
}

View File

@@ -96,6 +96,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
}
private bool keyboardManager = true;
[JsonPropertyName("Keyboard Manager")]
public bool KeyboardManager
{
@@ -112,7 +113,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
private bool powerLauncher = true;
[JsonPropertyName("PowerToys Run")]
[JsonPropertyName("PowerToys Run")]
public bool PowerLauncher
{
get => this.powerLauncher;
@@ -123,8 +124,24 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
LogTelemetryEvent(value);
this.powerLauncher = value;
}
}
}
}
}
private bool colorPicker = true;
[JsonPropertyName("ColorPicker")]
public bool ColorPicker
{
get => this.colorPicker;
set
{
if (this.colorPicker != value)
{
LogTelemetryEvent(value);
this.colorPicker = value;
}
}
}
public string ToJsonString()
{
@@ -141,4 +158,4 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
PowerToysTelemetry.Log.WriteEvent(dataEvent);
}
}
}
}

View File

@@ -111,6 +111,7 @@
<Compile Include="Helpers\ResourceExtensions.cs" />
<Compile Include="Services\ActivationService.cs" />
<Compile Include="Services\NavigationService.cs" />
<Compile Include="ViewModels\ColorPickerViewModel.cs" />
<Compile Include="ViewModels\Commands\ButtonClickCommand.cs" />
<Compile Include="ViewModels\GeneralViewModel.cs" />
<Compile Include="ViewModels\FancyZonesViewModel.cs" />
@@ -121,6 +122,9 @@
<Compile Include="ViewModels\PowerLauncherViewModel.cs" />
<Compile Include="ViewModels\ShellViewModel.cs" />
<Compile Include="ViewModels\ShortcutGuideViewModel.cs" />
<Compile Include="Views\ColorPickerPage.xaml.cs">
<DependentUpon>ColorPickerPage.xaml</DependentUpon>
</Compile>
<Compile Include="Views\GeneralPage.xaml.cs">
<DependentUpon>GeneralPage.xaml</DependentUpon>
</Compile>
@@ -241,6 +245,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\ColorPickerPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\GeneralPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

View File

@@ -157,6 +157,10 @@
<value>Image Resizer</value>
<comment>Navigation view item name for Image Resizer</comment>
</data>
<data name="Shell_ColorPicker.Content" xml:space="preserve">
<value>Color Picker</value>
<comment>Navigation view item name for Color Picker</comment>
</data>
<data name="Shell_KeyboardManager.Content" xml:space="preserve">
<value>Keyboard Manager</value>
<comment>Navigation view item name for Keyboard Manager</comment>
@@ -193,6 +197,21 @@
<value>Remap shortcuts</value>
<comment>Keyboard Manager remap shortcuts header</comment>
</data>
<data name="ColorPicker_Description.Text" xml:space="preserve">
<value>Quick and simple system-wide color picker</value>
</data>
<data name="ColorPicker_EnableColorPicker.Header" xml:space="preserve">
<value>Enable Color Picker</value>
</data>
<data name="ColorPicker_ChangeCursor.Header" xml:space="preserve">
<value>Change cursor when picking a color</value>
</data>
<data name="ColorPicker_CopiedColorRepresentation.Header" xml:space="preserve">
<value>Copied color representation</value>
</data>
<data name="ColorPicker_ActivationShortcut.Header" xml:space="preserve">
<value>Activation shortcut</value>
</data>
<data name="PowerLauncher_Description.Text" xml:space="preserve">
<value>A quick launcher that has additional capabilities without sacrificing performance.</value>
</data>
@@ -569,6 +588,9 @@
<data name="About_KeyboardManager.Text" xml:space="preserve">
<value>About Keyboard Manager</value>
</data>
<data name="About_ColorPicker.Text" xml:space="preserve">
<value>About Color Picker</value>
</data>
<data name="About_PowerLauncher.Text" xml:space="preserve">
<value>About PowerToys Run</value>
</data>

View File

@@ -0,0 +1,121 @@
// 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.Json;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Lib;
using Microsoft.PowerToys.Settings.UI.Views;
namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
public class ColorPickerViewModel : Observable
{
private ColorPickerSettings _colorPickerSettings;
private bool _isEnabled;
public ColorPickerViewModel()
{
if (SettingsUtils.SettingsExists(ColorPickerSettings.ModuleName))
{
_colorPickerSettings = SettingsUtils.GetSettings<ColorPickerSettings>(ColorPickerSettings.ModuleName);
}
else
{
_colorPickerSettings = new ColorPickerSettings();
}
if (SettingsUtils.SettingsExists())
{
var generalSettings = SettingsUtils.GetSettings<GeneralSettings>();
_isEnabled = generalSettings.Enabled.ColorPicker;
}
}
public bool IsEnabled
{
get
{
return _isEnabled;
}
set
{
if (_isEnabled != value)
{
_isEnabled = value;
OnPropertyChanged(nameof(IsEnabled));
// grab the latest version of settings
var generalSettings = SettingsUtils.GetSettings<GeneralSettings>();
generalSettings.Enabled.ColorPicker = value;
OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(generalSettings);
ShellPage.DefaultSndMSGCallback(outgoing.ToString());
}
}
}
public bool ChangeCursor
{
get
{
return _colorPickerSettings.properties.ChangeCursor;
}
set
{
if (_colorPickerSettings.properties.ChangeCursor != value)
{
_colorPickerSettings.properties.ChangeCursor = value;
OnPropertyChanged(nameof(ChangeCursor));
NotifySettingsChanged();
}
}
}
public HotkeySettings ActivationShortcut
{
get
{
return _colorPickerSettings.properties.ActivationShortcut;
}
set
{
if (_colorPickerSettings.properties.ActivationShortcut != value)
{
_colorPickerSettings.properties.ActivationShortcut = value;
OnPropertyChanged(nameof(ActivationShortcut));
NotifySettingsChanged();
}
}
}
public int CopiedColorRepresentationIndex
{
get
{
return (int)_colorPickerSettings.properties.CopiedColorRepresentation;
}
set
{
if (_colorPickerSettings.properties.CopiedColorRepresentation != (ColorRepresentationType)value)
{
_colorPickerSettings.properties.CopiedColorRepresentation = (ColorRepresentationType)value;
OnPropertyChanged(nameof(CopiedColorRepresentationIndex));
NotifySettingsChanged();
}
}
}
private void NotifySettingsChanged()
{
ShellPage.DefaultSndMSGCallback(
string.Format("{{ \"powertoys\": {{ \"{0}\": {1} }} }}", ColorPickerSettings.ModuleName, JsonSerializer.Serialize(_colorPickerSettings)));
}
}
}

View File

@@ -0,0 +1,107 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.Views.ColorPickerPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Views"
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"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid ColumnSpacing="{StaticResource DefaultColumnSpacing}" RowSpacing="{StaticResource DefaultRowSpacing}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="LayoutVisualStates">
<VisualState x:Name="WideLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource WideLayoutMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="SidePanel.(Grid.Column)" Value="1" />
<Setter Target="SidePanel.(Grid.Row)" Value="0" />
<Setter Target="SidePanel.Width" Value="{StaticResource SidePanelWidth}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="SmallLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="{StaticResource SmallLayoutMinWidth}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="SidePanel.(Grid.Column)" Value="0" />
<Setter Target="SidePanel.(Grid.Row)" Value="1" />
<Setter Target="SidePanel.Width" Value="Auto" />
</VisualState.Setters>
</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">
<TextBlock x:Uid="ColorPicker_Description"
TextWrapping="Wrap"/>
<ToggleSwitch x:Uid="ColorPicker_EnableColorPicker"
IsOn="{Binding IsEnabled, Mode=TwoWay}"
Margin="{StaticResource MediumTopMargin}"/>
<Custom:HotkeySettingsControl x:Uid="ColorPicker_ActivationShortcut"
Width="240"
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}"
HotkeySettings="{x:Bind Path=ViewModel.ActivationShortcut, Mode=TwoWay}"
IsEnabled="{Binding IsEnabled}"/>
<ComboBox x:Uid="ColorPicker_CopiedColorRepresentation"
SelectedIndex="{Binding CopiedColorRepresentationIndex, Mode=TwoWay}"
Width="240"
Margin="{StaticResource SmallTopMargin}"
IsEnabled="{Binding IsEnabled}">
<ComboBoxItem Content="HEX - #FFAA00"/>
<ComboBoxItem Content="RGB - RGB(100, 50, 75)"/>
</ComboBox>
<ToggleSwitch x:Uid="ColorPicker_ChangeCursor"
IsOn="{Binding ChangeCursor, Mode=TwoWay}"
Margin="{StaticResource MediumTopMargin}"
IsEnabled="{Binding IsEnabled}"/>
</StackPanel>
<StackPanel
x:Name="SidePanel"
Orientation="Vertical"
HorizontalAlignment="Left"
Width="{StaticResource SidePanelWidth}"
Grid.Column="1">
<TextBlock
x:Uid="About_ColorPicker"
Style="{StaticResource SettingsGroupTitleStyle}"
Margin="{StaticResource XSmallBottomMargin}"/>
<HyperlinkButton NavigateUri="https://aka.ms/PowerToysOverview_ColorPicker">
<TextBlock x:Uid="Module_overview" />
</HyperlinkButton>
<HyperlinkButton NavigateUri="https://github.com/microsoft/PowerToys/issues">
<TextBlock x:Uid="Give_Feedback" />
</HyperlinkButton>
<TextBlock
x:Uid="AttributionTitle"
Style="{StaticResource SettingsGroupTitleStyle}" />
<HyperlinkButton
NavigateUri="https://github.com/martinchrzan/ColorPicker/">
<TextBlock Text="Martin Chrzan's Color Picker" TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</Grid>
</Page>

View File

@@ -0,0 +1,17 @@
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Windows.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class ColorPickerPage : Page
{
public ColorPickerViewModel ViewModel { get; set; }
public ColorPickerPage()
{
ViewModel = new ColorPickerViewModel();
DataContext = ViewModel;
InitializeComponent();
}
}
}

View File

@@ -94,6 +94,12 @@
</winui:NavigationViewItem.Icon>
</winui:NavigationViewItem>
<winui:NavigationViewItem x:Uid="Shell_ColorPicker" helpers:NavHelper.NavigateTo="views:ColorPickerPage">
<winui:NavigationViewItem.Icon>
<FontIcon Glyph="&#xEF3C;"/>
</winui:NavigationViewItem.Icon>
</winui:NavigationViewItem>
</winui:NavigationView.MenuItems>
<i:Interaction.Behaviors>
<behaviors:NavigationViewHeaderBehavior

View File

@@ -159,6 +159,7 @@
<Compile Include="Generated Files\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="ViewModelTests\ColorPicker.cs" />
<Compile Include="ViewModelTests\FancyZones.cs" />
<Compile Include="ViewModelTests\General.cs" />
<Compile Include="ModelsTests\HelperTest.cs" />

View File

@@ -0,0 +1,59 @@
using Microsoft.PowerToys.Settings.UI.Lib;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using System.Text.Json;
namespace ViewModelTests
{
[TestClass]
public class ColorPicker
{
private const string ModuleName = "ColorPicker";
[TestInitialize]
public void Setup()
{
var generalSettings = new GeneralSettings();
var colorPickerSettings = new ColorPickerSettings();
SettingsUtils.SaveSettings(generalSettings.ToJsonString());
SettingsUtils.SaveSettings(colorPickerSettings.ToJsonString(), colorPickerSettings.name, ModuleName + ".json");
}
[TestCleanup]
public void CleanUp()
{
string generalSettings_file_name = string.Empty;
if (SettingsUtils.SettingsFolderExists(generalSettings_file_name))
{
DeleteFolder(generalSettings_file_name);
}
if (SettingsUtils.SettingsFolderExists(ModuleName))
{
DeleteFolder(ModuleName);
}
}
[TestMethod]
public void ColorPickerIsEnabledByDefault()
{
var viewModel = new ColorPickerViewModel();
ShellPage.DefaultSndMSGCallback = msg =>
{
OutGoingGeneralSettings snd = JsonSerializer.Deserialize<OutGoingGeneralSettings>(msg);
Assert.IsTrue(snd.GeneralSettings.Enabled.ColorPicker);
};
Assert.IsTrue(viewModel.IsEnabled);
}
private static void DeleteFolder(string powertoy)
{
Directory.Delete(Path.Combine(SettingsUtils.LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"), true);
}
}
}

View File

@@ -80,7 +80,6 @@ namespace ViewModelTests
viewModel.OpenPowerLauncher = openPowerLauncher;
viewModel.OpenFileLocation = openFileLocation;
viewModel.OpenConsole = openConsole;
viewModel.CopyPathLocation = copyFileLocation;
Assert.AreEqual(4, sendCallbackMock.TimesSent);