[Settings][runner]Quick access system tray launcher (#22408)

* Init

* Fix running settings

* UI design

* Left click trigger
Wire up colorpicker and pt run

* Wire up others

* Update FlyoutWindow.xaml.cs

* Removed comments

* Update FlyoutWindow.xaml

* More work

* Open Settings page

* More UI work

* Resolve conflicts

* [General] SystemTray Flyout: Add update on tray items' visibility when module gets enabled/disabled
Also remove context menu opening on tray icon.

* Adding app list

* Adding more buttons, resolving conflicts

* [General] Flyout: improving opening, closing flyout/settings window. Implementing basic bahaviour on enabling/disabling modules.

* [General] FlyoutWindow: proceed with implementation. GPO works. Main functionallity works (launching and enabling apps).

* [general] flyout: fix exit button

* [general] flyout: implement double click handling

* Localization

* [Generel] Flyout: Re-implement flyout launching, add workaround: disable flyout hiding in case the user switches on modules on the all apps page
+ minor changes

* [general] flyout: restore the context menu when right clicking on system tray icon

* Fix spellchecker

* [installer] fixing missing dll files + suppress error on not signed script

* Fix spell checker

* Fix flyout not focusing when activated

* Refresh Settings UI enabled state when flyout changes

* fix spellcheck

* Remove VCM from the list

* [General] flyout: fix settings window opening. Switch to general page only if there is no page opened

* [general] flyout: add launching hosts app

* Fix CI build

* adding check on elevation when launching hosts

* Use localization strings that already exist

* Remove dll not present in arm64 build

* Adding GPO policy check for the launcher page items

* fix hosts launching

* Add telemetry

* Also hide from all apps list when gpo is force enabling

* fix spellchecker

* Improve focus issues

* Fix flickering Bitmap Icons

* Fix telemetry error

* Fix telemetry call

* Fix wrong comment

---------

Co-authored-by: Stefan Markovic <stefan@janeasystems.com>
Co-authored-by: Laszlo Nemeth <laszlo.nemeth.hu@gmail.com>
Co-authored-by: Jaime Bernardo <jaime@janeasystems.com>
This commit is contained in:
Niels Laute 2023-01-31 00:00:11 +01:00 committed by GitHub
parent fb2b150a1d
commit c1c14b4f2e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
79 changed files with 2881 additions and 426 deletions

View File

@ -79,6 +79,7 @@
^\Q.pipelines/ESRPSigning_core.json\E$
^\Qsrc/modules/colorPicker/ColorPickerUI/Shaders/GridShader.cso\E$
^\Qsrc/common/ManagedCommon/ColorFormatHelper.cs\E$
^\Qinstaller/PowerToysSetup/Settings.wxs\E$
^\Qsrc/settings-ui/Settings.UI.UnitTests/BackwardsCompatibility/TestFiles/CorruptJson/Microsoft/PowerToys/settings.json\E$
^\Qsrc/settings-ui/Settings.UI.UnitTests/BackwardsCompatibility/TestFiles/v0.18.2/Microsoft/PowerToys/PowerRename/power-rename-ui-flags\E$
^\Qsrc/settings-ui/Settings.UI.UnitTests/BackwardsCompatibility/TestFiles/v0.19.2/Microsoft/PowerToys/PowerRename/power-rename-ui-flags\E$

View File

@ -201,6 +201,7 @@ CHILDACTIVATE
CHILDWINDOW
Choibalsan
chrdavis
chromaticities
Chrzan
cht
Chukotka
@ -848,6 +849,7 @@ Khakassia
Khanty
Khovd
KILLFOCUS
killrunner
Kitts
Knownfolders
Krai
@ -1446,6 +1448,7 @@ reencoded
REFCLSID
REFGUID
REFIID
Refreshable
REGCLS
regedit
regfile

View File

@ -4,7 +4,7 @@
<?include $(sys.CURRENTDIR)\Common.wxi?>
<?define SettingsV2Files=backup_restore_settings.json;Ijwhost.dll;ColorCode.Core.dll;ColorCode.WinUI.dll;CommunityToolkit.Common.dll;CommunityToolkit.Labs.WinUI.SettingsControls.dll;CommunityToolkit.WinUI.dll;CommunityToolkit.WinUI.UI.Controls.Core.dll;CommunityToolkit.WinUI.UI.Controls.DataGrid.dll;CommunityToolkit.WinUI.UI.Controls.Input.dll;CommunityToolkit.WinUI.UI.Controls.Layout.dll;CommunityToolkit.WinUI.UI.Controls.Markdown.dll;CommunityToolkit.WinUI.UI.Controls.Media.dll;CommunityToolkit.WinUI.UI.Controls.Primitives.dll;CommunityToolkit.WinUI.UI.dll;icon.ico;Microsoft.Graphics.Canvas.Interop.dll;Microsoft.InteractiveExperiences.Projection.dll;Microsoft.Windows.ApplicationModel.DynamicDependency.Projection.dll;Microsoft.Windows.ApplicationModel.Resources.Projection.dll;Microsoft.Windows.ApplicationModel.WindowsAppRuntime.Projection.dll;Microsoft.Windows.AppLifecycle.Projection.dll;Microsoft.Windows.SDK.NET.dll;Microsoft.Windows.System.Power.Projection.dll;Microsoft.WindowsAppRuntime.Bootstrap.Net.dll;Microsoft.WinUI.dll;Microsoft.Xaml.Interactions.dll;Microsoft.Xaml.Interactivity.dll;PowerToys.ManagedCommon.dll;PowerToys.ManagedTelemetry.dll;PowerToys.Settings.deps.json;PowerToys.Settings.dll;PowerToys.Settings.exe;PowerToys.Settings.runtimeconfig.json;PowerToys.Settings.UI.Lib.dll;resources.pri;System.CodeDom.dll;System.IO.Abstractions.dll;WinRT.Runtime.dll;Microsoft.Graphics.Canvas.dll;System.Management.dll;PowerToys.GPOWrapper.dll;System.Text.Json.dll;WindowsBase.dll?>
<?define SettingsV2Files=WinUIEx.dll;backup_restore_settings.json;Ijwhost.dll;ColorCode.Core.dll;ColorCode.WinUI.dll;CommunityToolkit.Common.dll;CommunityToolkit.Labs.WinUI.SettingsControls.dll;CommunityToolkit.WinUI.dll;CommunityToolkit.WinUI.UI.Controls.Core.dll;CommunityToolkit.WinUI.UI.Controls.DataGrid.dll;CommunityToolkit.WinUI.UI.Controls.Input.dll;CommunityToolkit.WinUI.UI.Controls.Layout.dll;CommunityToolkit.WinUI.UI.Controls.Markdown.dll;CommunityToolkit.WinUI.UI.Controls.Media.dll;CommunityToolkit.WinUI.UI.Controls.Primitives.dll;CommunityToolkit.WinUI.UI.dll;icon.ico;Microsoft.Graphics.Canvas.Interop.dll;Microsoft.InteractiveExperiences.Projection.dll;Microsoft.Windows.ApplicationModel.DynamicDependency.Projection.dll;Microsoft.Windows.ApplicationModel.Resources.Projection.dll;Microsoft.Windows.ApplicationModel.WindowsAppRuntime.Projection.dll;Microsoft.Windows.AppLifecycle.Projection.dll;Microsoft.Windows.SDK.NET.dll;Microsoft.Windows.System.Power.Projection.dll;Microsoft.WindowsAppRuntime.Bootstrap.Net.dll;Microsoft.WinUI.dll;Microsoft.Xaml.Interactions.dll;Microsoft.Xaml.Interactivity.dll;PowerToys.ManagedCommon.dll;PowerToys.ManagedTelemetry.dll;PowerToys.Settings.deps.json;PowerToys.Settings.dll;PowerToys.Settings.exe;PowerToys.Settings.runtimeconfig.json;PowerToys.Settings.UI.Lib.dll;resources.pri;System.CodeDom.dll;System.IO.Abstractions.dll;WinRT.Runtime.dll;Microsoft.Graphics.Canvas.dll;System.Management.dll;PowerToys.GPOWrapper.dll;System.Text.Json.dll;WindowsBase.dll?>
<?define SettingsV2AssetsModulesFiles=ColorPicker.png;FancyZones.png;FileLocksmith.png;AlwaysOnTop.png;HostsFileEditor.png;Awake.png;ImageResizer.png;KBM.png;MouseUtils.png;PowerAccent.png;PowerOCR.png;PowerLauncher.png;PowerPreview.png;PowerRename.png;PT.png;ScreenRuler.png;ShortcutGuide.png;VideoConference.png?>
<?define SettingsV2OOBEAssetsModulesFiles=ColorPicker.gif;AlwaysOnTop.png;HostsFileEditor.png;Awake.png;FancyZones.gif;FileExplorer.png;FileLocksmith.gif;ImageResizer.gif;KBM.gif;MouseUtils.gif;PowerAccent.gif;PowerOCR.gif;PowerRename.gif;Run.gif;ScreenRuler.gif;OOBEShortcutGuide.png;VideoConferenceMute.png;OOBEPTHero.png?>
<?define SettingsV2OOBEAssetsFluentIconsFiles=ColorPicker.png;FancyZones.png;FileLocksmith.png;AlwaysOnTop.png;Awake.png;FileExplorerPreview.png;FindMyMouse.png;Hosts.png;ImageResizer.png;KeyboardManager.png;MouseHighlighter.png;MouseCrosshairs.png;MouseUtils.png;PowerAccent.png;PowerOcr.png;PowerRename.png;PowerToys.png;PowerToysRun.png;ScreenRuler.png;Settings.png;ShortcutGuide.png;VideoConferenceMute.png?>

View File

@ -187,6 +187,10 @@ public
return gcnew String(CommonSharedConstants::FZE_EXIT_EVENT);
}
static String ^ FZEToggleEvent() {
return gcnew String(CommonSharedConstants::FANCY_ZONES_EDITOR_TOGGLE_EVENT);
}
static String ^ ColorPickerSendSettingsTelemetryEvent() {
return gcnew String(CommonSharedConstants::COLOR_PICKER_SEND_SETTINGS_TELEMETRY_EVENT);
}
@ -207,6 +211,14 @@ public
return gcnew String(CommonSharedConstants::POWERACCENT_EXIT_EVENT);
}
static String ^ ShortcutGuideTriggerEvent() {
return gcnew String(CommonSharedConstants::SHORTCUT_GUIDE_TRIGGER_EVENT);
}
static String
^ MeasureToolTriggerEvent() {
return gcnew String(CommonSharedConstants::MEASURE_TOOL_TRIGGER_EVENT);
}
static String ^ GcodePreviewResizeEvent() {
return gcnew String(CommonSharedConstants::GCODE_PREVIEW_RESIZE_EVENT);
}

View File

@ -28,6 +28,8 @@ namespace CommonSharedConstants
// Path to the event used to show Color Picker
const wchar_t SHOW_COLOR_PICKER_SHARED_EVENT[] = L"Local\\ShowColorPickerEvent-8c46be2a-3e05-4186-b56b-4ae986ef2525";
const wchar_t SHORTCUT_GUIDE_TRIGGER_EVENT[] = L"Local\\ShortcutGuide-TriggerEvent-d4275ad3-2531-4d19-9252-c0becbd9b496";
const wchar_t SHORTCUT_GUIDE_EXIT_EVENT[] = L"Local\\ShortcutGuide-ExitEvent-35697cdd-a3d2-47d6-a246-34efcc73eac0";
const wchar_t FANCY_ZONES_EDITOR_TOGGLE_EVENT[] = L"Local\\FancyZones-ToggleEditorEvent-1e174338-06a3-472b-874d-073b21c62f14";
@ -44,6 +46,9 @@ namespace CommonSharedConstants
// Path to the event used by PowerOCR
const wchar_t SHOW_POWEROCR_SHARED_EVENT[] = L"Local\\PowerOCREvent-dc864e06-e1af-4ecc-9078-f98bee745e3a";
// Path to the event used by MeasureTool
const wchar_t MEASURE_TOOL_TRIGGER_EVENT[] = L"Local\\MeasureToolEvent-3d46745f-09b3-4671-a577-236be7abd199";
// Path to the event used by GcodePreviewHandler
const wchar_t GCODE_PREVIEW_RESIZE_EVENT[] = L"Local\\PowerToysGcodePreviewResizeEvent-6ff1f9bd-ccbd-4b24-a79f-40a34fb0317d";

View File

@ -3,9 +3,11 @@
#include <interface/powertoy_module_interface.h>
#include <common/SettingsAPI/settings_objects.h>
#include "trace.h"
#include <common/interop/shared_constants.h>
#include <common/utils/string_utils.h>
#include <common/utils/winapi_error.h>
#include <common/utils/logger_helper.h>
#include <common/utils/EventWaiter.h>
extern "C" IMAGE_DOS_HEADER __ImageBase;
@ -49,6 +51,9 @@ private:
Hotkey m_hotkey;
HANDLE m_hProcess;
HANDLE triggerEvent;
EventWaiter triggerEventWaiter;
void parse_hotkey(PowerToysSettings::PowerToyValues& settings)
{
auto settingsObject = settings.get_raw_json();
@ -142,6 +147,11 @@ public:
{
LoggerHelpers::init_logger(L"Measure Tool", L"ModuleInterface", "Measure Tool");
init_settings();
triggerEvent = CreateEvent(nullptr, false, false, CommonSharedConstants::MEASURE_TOOL_TRIGGER_EVENT);
triggerEventWaiter = EventWaiter(CommonSharedConstants::MEASURE_TOOL_TRIGGER_EVENT, [this](int) {
on_hotkey(0);
});
}
~MeasureTool()

View File

@ -5,8 +5,8 @@
xmlns:contract7NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,7)"
xmlns:contract7Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,7)"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:p="using:PowerToys.MeasureToolUI.Properties"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:p="using:PowerToys.MeasureToolUI.Properties"
xmlns:winuiex="using:WinUIEx"
IsAlwaysOnTop="True"
IsMaximizable="False"

View File

@ -10,6 +10,7 @@
#include "../interface/powertoy_module_interface.h"
#include "Generated Files/resource.h"
#include <common/SettingsAPI/settings_objects.h>
#include <common/utils/EventWaiter.h>
BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD /*ul_reason_for_call*/, LPVOID /*lpReserved*/)
{
@ -35,6 +36,11 @@ public:
Logger::warn(L"Failed to create {} event. {}", CommonSharedConstants::SHORTCUT_GUIDE_EXIT_EVENT, get_last_error_or_default(GetLastError()));
}
triggerEvent = CreateEvent(nullptr, false, false, CommonSharedConstants::SHORTCUT_GUIDE_TRIGGER_EVENT);
triggerEventWaiter = EventWaiter(CommonSharedConstants::SHORTCUT_GUIDE_TRIGGER_EVENT, [this](int) {
OnHotkeyEx();
});
InitSettings();
}
@ -191,7 +197,9 @@ private:
UINT m_millisecondsWinKeyPressTimeForGlobalWindowsShortcuts = DEFAULT_MILLISECONDS_WIN_KEY_PRESS_TIME_FOR_GLOBAL_WINDOWS_SHORTCUTS;
UINT m_millisecondsWinKeyPressTimeForTaskbarIconShortcuts = DEFAULT_MILLISECONDS_WIN_KEY_PRESS_TIME_FOR_TASKBAR_ICON_SHORTCUTS;
HANDLE triggerEvent;
HANDLE exitEvent;
EventWaiter triggerEventWaiter;
bool StartProcess(std::wstring args = L"")
{

View File

@ -203,7 +203,7 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow
{
window = winrt::to_hstring(settingsWindow);
}
open_settings_window(window);
open_settings_window(window, false);
}
if (openOobe)

View File

@ -11,12 +11,14 @@
#include "restart_elevated.h"
#include "UpdateUtils.h"
#include "centralized_kb_hook.h"
#include "Generated files/resource.h"
#include <common/utils/json.h>
#include <common/SettingsAPI/settings_helpers.cpp>
#include <common/version/version.h>
#include <common/version/helper.h>
#include <common/logger/logger.h>
#include <common/utils/resources.h>
#include <common/utils/elevation.h>
#include <common/utils/process_path.h>
#include <common/utils/timeutil.h>
@ -175,7 +177,7 @@ void dispatch_received_json(const std::wstring& json_to_parse)
const std::wstring settings_string{ get_all_settings().Stringify().c_str() };
{
std::unique_lock lock{ ipc_mutex };
if(current_settings_ipc)
if (current_settings_ipc)
current_settings_ipc->send(settings_string);
}
}
@ -185,7 +187,7 @@ void dispatch_received_json(const std::wstring& json_to_parse)
const std::wstring settings_string{ get_all_settings().Stringify().c_str() };
{
std::unique_lock lock{ ipc_mutex };
if(current_settings_ipc)
if (current_settings_ipc)
current_settings_ipc->send(settings_string);
}
}
@ -194,7 +196,7 @@ void dispatch_received_json(const std::wstring& json_to_parse)
const std::wstring settings_string{ get_all_settings().Stringify().c_str() };
{
std::unique_lock lock{ ipc_mutex };
if(current_settings_ipc)
if (current_settings_ipc)
current_settings_ipc->send(settings_string);
}
}
@ -205,11 +207,35 @@ void dispatch_received_json(const std::wstring& json_to_parse)
{
{
std::unique_lock lock{ ipc_mutex };
if(current_settings_ipc)
if (current_settings_ipc)
current_settings_ipc->send(result.value());
}
}
}
else if (name == L"bugreport")
{
std::wstring bug_report_path = get_module_folderpath();
bug_report_path += L"\\Tools\\PowerToys.BugReportTool.exe";
SHELLEXECUTEINFOW sei{ sizeof(sei) };
sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE };
sei.lpFile = bug_report_path.c_str();
sei.nShow = SW_HIDE;
if (ShellExecuteExW(&sei))
{
WaitForSingleObject(sei.hProcess, INFINITE);
CloseHandle(sei.hProcess);
static const std::wstring bugreport_success = GET_RESOURCE_STRING(IDS_BUGREPORT_SUCCESS);
MessageBoxW(nullptr, bugreport_success.c_str(), L"PowerToys", MB_OK);
}
}
else if (name == L"killrunner")
{
const auto pt_main_window = FindWindowW(pt_tray_icon_window_class, nullptr);
if (pt_main_window != nullptr)
{
SendMessageW(pt_main_window, WM_CLOSE, 0, 0);
}
}
}
return;
}
@ -290,7 +316,7 @@ BOOL run_settings_non_elevated(LPCWSTR executable_path, LPWSTR executable_args,
DWORD g_settings_process_id = 0;
void run_settings_window(bool show_oobe_window, bool show_scoobe_window, std::optional<std::wstring> settings_window)
void run_settings_window(bool show_oobe_window, bool show_scoobe_window, std::optional<std::wstring> settings_window, bool show_flyout = false)
{
g_isLaunchInProgress = true;
@ -360,11 +386,14 @@ void run_settings_window(bool show_oobe_window, bool show_scoobe_window, std::op
// Arg 9: should scoobe window be shown
std::wstring settings_showScoobe = show_scoobe_window ? L"true" : L"false";
// Arg 10: should flyout be shown
std::wstring settings_showFlyout = show_flyout ? L"true" : L"false";
// create general settings file to initialize the settings file with installation configurations like :
// 1. Run on start up.
PTSettingsHelper::save_general_settings(save_settings.to_json());
std::wstring executable_args = fmt::format(L"\"{}\" {} {} {} {} {} {} {} {}",
std::wstring executable_args = fmt::format(L"\"{}\" {} {} {} {} {} {} {} {} {}",
executable_path,
powertoys_pipe_name,
settings_pipe_name,
@ -373,7 +402,8 @@ void run_settings_window(bool show_oobe_window, bool show_scoobe_window, std::op
settings_elevatedStatus,
settings_isUserAnAdmin,
settings_showOobe,
settings_showScoobe);
settings_showScoobe,
settings_showFlyout);
if (settings_window.has_value())
{
@ -520,18 +550,33 @@ void bring_settings_to_front()
EnumWindows(callback, 0);
}
void open_settings_window(std::optional<std::wstring> settings_window)
void open_settings_window(std::optional<std::wstring> settings_window, bool show_flyout = false)
{
if (g_settings_process_id != 0)
{
bring_settings_to_front();
if (show_flyout)
{
if (current_settings_ipc)
{
current_settings_ipc->send(L"{\"ShowYourself\":\"flyout\"}");
}
}
else
{
// nl instead of showing the window, send message to it (flyout might need to be hidden, main setting window activated)
// bring_settings_to_front();
if (current_settings_ipc)
{
current_settings_ipc->send(L"{\"ShowYourself\":\"main_page\"}");
}
}
}
else
{
if (!g_isLaunchInProgress)
{
std::thread([settings_window]() {
run_settings_window(false, false, settings_window);
std::thread([settings_window, show_flyout]() {
run_settings_window(false, false, settings_window, show_flyout);
}).detach();
}
}
@ -563,6 +608,13 @@ void open_scoobe_window()
}).detach();
}
void open_flyout()
{
std::thread([]() {
run_settings_window(false, false, std::nullopt, true);
}).detach();
}
std::string ESettingsWindowNames_to_string(ESettingsWindowNames value)
{
switch (value)

View File

@ -22,8 +22,9 @@ enum class ESettingsWindowNames
std::string ESettingsWindowNames_to_string(ESettingsWindowNames value);
ESettingsWindowNames ESettingsWindowNames_from_string(std::string value);
void open_settings_window(std::optional<std::wstring> settings_window);
void open_settings_window(std::optional<std::wstring> settings_window, bool show_flyout);
void close_settings_window();
void open_oobe_window();
void open_scoobe_window();
void open_flyout();

View File

@ -30,6 +30,8 @@ namespace
HMENU h_menu = nullptr;
HMENU h_sub_menu = nullptr;
bool double_click_timer_running = false;
bool double_clicked = false;
}
// Struct to fill with callback and the data. The window_proc is responsible for cleaning it.
@ -69,7 +71,7 @@ void handle_tray_command(HWND window, const WPARAM command_id, LPARAM lparam)
case ID_SETTINGS_MENU_COMMAND:
{
std::wstring settings_window{ winrt::to_hstring(ESettingsWindowNames_to_string(static_cast<ESettingsWindowNames>(lparam))) };
open_settings_window(settings_window);
open_settings_window(settings_window, false);
}
break;
case ID_EXIT_MENU_COMMAND:
@ -116,6 +118,15 @@ void handle_tray_command(HWND window, const WPARAM command_id, LPARAM lparam)
}
}
void click_timer_elapsed()
{
double_click_timer_running = false;
if (!double_clicked)
{
open_settings_window(std::nullopt, true);
}
}
LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
{
switch (message)
@ -168,11 +179,6 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam
{
switch (lparam)
{
case WM_LBUTTONDBLCLK:
{
open_settings_window(std::nullopt);
break;
}
case WM_RBUTTONUP:
case WM_CONTEXTMENU:
{
@ -186,7 +192,6 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam
static std::wstring exit_menuitem_label = GET_RESOURCE_STRING(IDS_EXIT_MENU_TEXT);
static std::wstring submit_bug_menuitem_label = GET_RESOURCE_STRING(IDS_SUBMIT_BUG_TEXT);
static std::wstring documentation_menuitem_label = GET_RESOURCE_STRING(IDS_DOCUMENTATION_MENU_TEXT);
change_menu_item_text(ID_SETTINGS_MENU_COMMAND, settings_menuitem_label.data());
change_menu_item_text(ID_EXIT_MENU_COMMAND, exit_menuitem_label.data());
change_menu_item_text(ID_REPORT_BUG_COMMAND, submit_bug_menuitem_label.data());
@ -200,6 +205,30 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam
GetCursorPos(&mouse_pointer);
SetForegroundWindow(window); // Needed for the context menu to disappear.
TrackPopupMenu(h_sub_menu, TPM_CENTERALIGN | TPM_BOTTOMALIGN, mouse_pointer.x, mouse_pointer.y, 0, window, nullptr);
break;
}
case WM_LBUTTONUP:
{
// ignore event if this is the second click of a double click
if (!double_click_timer_running)
{
// start timer for detecting single or double click
double_click_timer_running = true;
double_clicked = false;
UINT doubleClickTime = GetDoubleClickTime();
std::thread([doubleClickTime]() {
std::this_thread::sleep_for(std::chrono::milliseconds(doubleClickTime));
click_timer_elapsed();
}).detach();
}
break;
}
case WM_LBUTTONDBLCLK:
{
double_clicked = true;
open_settings_window(std::nullopt, false);
break;
}
break;
}

View File

@ -7,7 +7,7 @@ void start_tray_icon();
// Stop the Tray Icon
void stop_tray_icon();
// Open the Settings Window
void open_settings_window(std::optional<std::wstring> settings_window);
void open_settings_window(std::optional<std::wstring> settings_window, bool show_flyout);
// Callback type to be called by the tray icon loop
typedef void (*main_loop_callback_function)(PVOID);
// Calls a callback in _callback

View File

@ -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;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Text.Json.Serialization;
@ -12,6 +13,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library
{
public class EnabledModules
{
private Action notifyEnabledChangedAction;
public EnabledModules()
{
}
@ -28,6 +31,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
{
LogTelemetryEvent(value);
fancyZones = value;
NotifyChange();
}
}
}
@ -76,6 +80,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
{
LogTelemetryEvent(value);
shortcutGuide = value;
NotifyChange();
}
}
}
@ -139,6 +144,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
{
LogTelemetryEvent(value);
powerLauncher = value;
NotifyChange();
}
}
}
@ -155,6 +161,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
{
LogTelemetryEvent(value);
colorPicker = value;
NotifyChange();
}
}
}
@ -267,6 +274,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
{
LogTelemetryEvent(value);
powerOCR = value;
NotifyChange();
}
}
}
@ -283,6 +291,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
{
LogTelemetryEvent(value);
measureTool = value;
NotifyChange();
}
}
}
@ -299,6 +308,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
{
LogTelemetryEvent(value);
hosts = value;
NotifyChange();
}
}
}
@ -319,6 +329,11 @@ namespace Microsoft.PowerToys.Settings.UI.Library
}
}
private void NotifyChange()
{
notifyEnabledChangedAction?.Invoke();
}
public string ToJsonString()
{
return JsonSerializer.Serialize(this);
@ -333,5 +348,10 @@ namespace Microsoft.PowerToys.Settings.UI.Library
};
PowerToysTelemetry.Log.WriteEvent(dataEvent);
}
internal void AddEnabledModuleChangeNotification(Action callBack)
{
notifyEnabledChangedAction = callBack;
}
}
}

View File

@ -108,5 +108,10 @@ namespace Microsoft.PowerToys.Settings.UI.Library
return false;
}
public void AddEnabledModuleChangeNotification(Action callBack)
{
Enabled.AddEnabledModuleChangeNotification(callBack);
}
}
}

View File

@ -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.Diagnostics.Tracing;
using Microsoft.PowerToys.Telemetry;
using Microsoft.PowerToys.Telemetry.Events;
namespace Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events
{
[EventData]
public class TrayFlyoutActivatedEvent : EventBase, IEvent
{
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
}
}

View File

@ -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.
using System.Diagnostics.Tracing;
using Microsoft.PowerToys.Telemetry;
using Microsoft.PowerToys.Telemetry.Events;
namespace Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events
{
[EventData]
public class TrayFlyoutModuleRunEvent : EventBase, IEvent
{
public string ModuleName { get; set; }
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
}
}

View File

@ -3,6 +3,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:local="using:Microsoft.PowerToys.Settings.UI"
xmlns:converters="using:CommunityToolkit.WinUI.UI.Converters"
xmlns:labs="using:CommunityToolkit.Labs.WinUI">
<Application.Resources>

View File

@ -13,6 +13,7 @@ using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.PowerToys.Telemetry;
using Microsoft.UI.Xaml;
using Windows.UI.Popups;
@ -35,12 +36,13 @@ namespace Microsoft.PowerToys.Settings.UI
IsUserAdmin,
ShowOobeWindow,
ShowScoobeWindow,
ShowFlyout,
SettingsWindow,
}
// Quantity of arguments
private const int RequiredArgumentsQty = 9;
private const int RequiredAndOptionalArgumentsQty = 10;
private const int RequiredArgumentsQty = 10;
private const int RequiredAndOptionalArgumentsQty = 11;
// Create an instance of the IPC wrapper.
private static TwoWayPipeMessageIPCManaged ipcmanager;
@ -53,6 +55,8 @@ namespace Microsoft.PowerToys.Settings.UI
public bool ShowOobe { get; set; }
public bool ShowFlyout { get; set; }
public bool ShowScoobe { get; set; }
public Type StartupPage { get; set; } = typeof(Views.GeneralPage);
@ -71,15 +75,24 @@ namespace Microsoft.PowerToys.Settings.UI
this.InitializeComponent();
}
public static void OpenSettingsWindow(Type type)
public static void OpenSettingsWindow(Type type = null, bool ensurePageIsSelected = false)
{
if (settingsWindow == null)
{
settingsWindow = new MainWindow(IsDarkTheme());
type = typeof(GeneralPage);
}
settingsWindow.Activate();
settingsWindow.NavigateToSection(type);
if (type != null)
{
settingsWindow.NavigateToSection(type);
}
if (ensurePageIsSelected)
{
settingsWindow.EnsurePageIsSelected();
}
}
/// <summary>
@ -90,6 +103,7 @@ namespace Microsoft.PowerToys.Settings.UI
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
var cmdArgs = Environment.GetCommandLineArgs();
var isDark = IsDarkTheme();
if (cmdArgs != null && cmdArgs.Length >= RequiredArgumentsQty)
@ -107,6 +121,7 @@ namespace Microsoft.PowerToys.Settings.UI
IsUserAnAdmin = cmdArgs[(int)Arguments.IsUserAdmin] == "true";
ShowOobe = cmdArgs[(int)Arguments.ShowOobeWindow] == "true";
ShowScoobe = cmdArgs[(int)Arguments.ShowScoobeWindow] == "true";
ShowFlyout = cmdArgs[(int)Arguments.ShowFlyout] == "true";
if (cmdArgs.Length == RequiredAndOptionalArgumentsQty)
{
@ -149,7 +164,7 @@ namespace Microsoft.PowerToys.Settings.UI
});
ipcmanager.Start();
if (!ShowOobe && !ShowScoobe)
if (!ShowOobe && !ShowScoobe && !ShowFlyout)
{
settingsWindow = new MainWindow(isDark);
settingsWindow.Activate();
@ -176,6 +191,10 @@ namespace Microsoft.PowerToys.Settings.UI
scoobeWindow.Activate();
SetOobeWindow(scoobeWindow);
}
else if (ShowFlyout)
{
ShellPage.OpenFlyoutCallback();
}
}
}
else
@ -277,6 +296,7 @@ namespace Microsoft.PowerToys.Settings.UI
private static MainWindow settingsWindow;
private static OobeWindow oobeWindow;
private static FlyoutWindow flyoutWindow;
private static ThemeListener themeListener;
public static void ClearSettingsWindow()
@ -294,14 +314,29 @@ namespace Microsoft.PowerToys.Settings.UI
return oobeWindow;
}
public static FlyoutWindow GetFlyoutWindow()
{
return flyoutWindow;
}
public static void SetOobeWindow(OobeWindow window)
{
oobeWindow = window;
}
public static void SetFlyoutWindow(FlyoutWindow window)
{
flyoutWindow = window;
}
public static void ClearOobeWindow()
{
oobeWindow = null;
}
public static void ClearFlyoutWindow()
{
flyoutWindow = null;
}
}
}

View File

@ -0,0 +1,43 @@
// 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 CommunityToolkit.Labs.WinUI;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using WinUIEx;
namespace Microsoft.PowerToys.Settings.UI.Controls
{
public partial class FlyoutMenuButton : Button
{
/// <summary>
/// The backing <see cref="DependencyProperty"/> for the <see cref="Icon"/> property.
/// </summary>
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(
nameof(Icon),
typeof(object),
typeof(FlyoutMenuButton),
new PropertyMetadata(defaultValue: null));
/// <summary>
/// Gets or sets the icon.
/// </summary>
public object Icon
{
get => (object)GetValue(IconProperty);
set => SetValue(IconProperty, value);
}
public FlyoutMenuButton()
{
this.DefaultStyleKey = typeof(FlyoutMenuButton);
}
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
}
}
}

View File

@ -0,0 +1,104 @@
<!-- Copyright (c) Microsoft Corporation and Contributors. -->
<!-- Licensed under the MIT License. -->
<ResourceDictionary
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.Controls">
<Style BasedOn="{StaticResource DefaultFlyoutMenuButtonStyle}" TargetType="local:FlyoutMenuButton" />
<Style x:Key="DefaultFlyoutMenuButtonStyle" TargetType="local:FlyoutMenuButton">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="Width" Value="116" />
<Setter Property="Height" Value="84" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
<Setter Property="FocusVisualMargin" Value="-3" />
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:FlyoutMenuButton">
<Grid
x:Name="RootGrid"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="Transparent"
BackgroundSizing="InnerBorderEdge"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid.BackgroundTransition>
<BrushTransition Duration="0:0:0.083" />
</Grid.BackgroundTransition>
<ContentPresenter
x:Name="ContentPresenter"
Margin="0,52,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Content="{TemplateBinding Content}" />
<ContentPresenter
x:Name="IconPresenter"
Width="32"
Margin="0,12,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Content="{TemplateBinding Icon}"
RenderTransformOrigin="0.5, 0.5">
<ContentPresenter.RenderTransform>
<CompositeTransform />
</ContentPresenter.RenderTransform>
</ContentPresenter>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ControlFillColorDefaultBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="IconPresenter" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)">
<SplineDoubleKeyFrame
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFastAnimationDuration}"
Value="0.86" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="IconPresenter" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)">
<SplineDoubleKeyFrame
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFastAnimationDuration}"
Value="0.86" />
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ControlFillColorDefaultBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@ -0,0 +1,89 @@
<!-- Copyright (c) Microsoft Corporation and Contributors. -->
<!-- Licensed under the MIT License. -->
<Page
x:Class="Microsoft.PowerToys.Settings.UI.Flyout.AppsListPage"
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:local="using:Microsoft.PowerToys.Settings.UI.Flyout"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewmodels="using:Microsoft.PowerToys.Settings.UI.ViewModels"
mc:Ignorable="d">
<Grid Background="{ThemeResource LayerOnAcrylicFillColorDefaultBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Padding="24,32,24,0">
<TextBlock
x:Uid="AllAppsTxt"
VerticalAlignment="Center"
Style="{StaticResource BodyStrongTextBlockStyle}" />
<Button
x:Uid="BackBtn"
Padding="8,4,8,4"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Click="BackButton_Click">
<Button.Content>
<StackPanel
VerticalAlignment="Center"
Orientation="Horizontal"
Spacing="12">
<FontIcon
Margin="0,2,0,0"
FontSize="12"
Glyph="&#xe76b;" />
<TextBlock x:Uid="BackLabel" Style="{StaticResource CaptionTextBlockStyle}" />
</StackPanel>
</Button.Content>
</Button>
</Grid>
<ListView
Grid.Row="1"
Margin="0,16,0,0"
ItemsSource="{x:Bind ViewModel.FlyoutMenuItems}"
SelectionMode="None">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Padding="0,0,0,16" Orientation="Vertical" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate x:DataType="viewmodels:FlyoutMenuItem">
<Grid Height="40" Padding="24,0,24,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!--<ViewBox VerticalAlignment="Center">-->
<Image
Width="20"
Margin="0,0,16,0">
<Image.Source>
<BitmapImage UriSource="{x:Bind Icon, Mode=OneWay}" />
</Image.Source>
</Image>
<!--</ViewBox>-->
<TextBlock
Grid.Column="1"
VerticalAlignment="Center"
Text="{x:Bind Label, Mode=OneWay}"
TextTrimming="CharacterEllipsis" />
<ToggleSwitch
Grid.Column="2"
Margin="0,0,0,0"
HorizontalAlignment="Right"
AutomationProperties.Name="{x:Bind Label, Mode=OneWay}"
IsOn="{x:Bind IsEnabled, Mode=TwoWay}"
Style="{StaticResource RightAlignedCompactToggleSwitchStyle}" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Page>

View File

@ -0,0 +1,36 @@
// 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 global::Windows.System;
using interop;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media.Animation;
namespace Microsoft.PowerToys.Settings.UI.Flyout
{
public sealed partial class AppsListPage : Page
{
private AllAppsViewModel ViewModel { get; set; }
public AppsListPage()
{
this.InitializeComponent();
var settingsUtils = new SettingsUtils();
ViewModel = new AllAppsViewModel(SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), Views.ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
}
private void BackButton_Click(object sender, RoutedEventArgs e)
{
Frame.Navigate(typeof(LaunchPage), null, new SlideNavigationTransitionInfo() { Effect = SlideNavigationTransitionEffect.FromLeft });
}
}
}

View File

@ -0,0 +1,166 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.Flyout.LaunchPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:animatedVisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Flyout"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitControls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:viewModels="using:Microsoft.PowerToys.Settings.UI.ViewModels"
mc:Ignorable="d">
<Page.Resources>
<Style
x:Key="FlyoutButtonStyle"
BasedOn="{StaticResource SubtleButtonStyle}"
TargetType="Button">
<Setter Property="Padding" Value="6" />
<Setter Property="Width" Value="32" />
<Setter Property="Height" Value="32" />
<Setter Property="FontFamily" Value="{ThemeResource SymbolThemeFontFamily}" />
</Style>
</Page.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="48" />
</Grid.RowDefinitions>
<Grid
Background="{ThemeResource LayerOnAcrylicFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="0,0,0,1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Padding="36,32,36,0">
<TextBlock
VerticalAlignment="Center"
Style="{StaticResource BodyStrongTextBlockStyle}"
x:Uid="ShortcutsTxt" />
<Button
Padding="8,4,8,4"
HorizontalAlignment="Right"
VerticalAlignment="Center"
x:Uid="MoreBtn"
Click="AllAppButton_Click">
<Button.Content>
<StackPanel
VerticalAlignment="Center"
Orientation="Horizontal"
Spacing="12">
<TextBlock Style="{StaticResource CaptionTextBlockStyle}" x:Uid="MoreLabel" />
<FontIcon
Margin="0,2,0,0"
FontSize="12"
Glyph="&#xe76c;" />
</StackPanel>
</Button.Content>
</Button>
</Grid>
<Grid Grid.Row="1">
<ItemsControl
Margin="12,26,12,24"
HorizontalAlignment="Center"
VerticalAlignment="Top"
ItemsSource="{x:Bind ViewModel.FlyoutMenuItems}"
TabNavigation="Local">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<toolkitControls:WrapPanel VerticalSpacing="12" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="viewModels:FlyoutMenuItem">
<controls:FlyoutMenuButton
Click="ModuleButton_Click"
Tag="{x:Bind Tag}"
AutomationProperties.Name="{x:Bind Label}"
ToolTipService.ToolTip="{x:Bind ToolTip}"
Visibility="{x:Bind Visible, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BoolToVisibilityConverter}}">
<controls:FlyoutMenuButton.Content>
<TextBlock
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind Label}"
TextAlignment="Center"
TextWrapping="Wrap" />
</controls:FlyoutMenuButton.Content>
<controls:FlyoutMenuButton.Icon>
<Image>
<Image.Source>
<BitmapImage UriSource="{x:Bind Icon, Mode=OneWay}" />
</Image.Source>
</Image>
</controls:FlyoutMenuButton.Icon>
</controls:FlyoutMenuButton>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Grid>
<Grid Grid.Row="2">
<InfoBar
x:Uid="UpdateAvailable"
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsUpdateAvailable, Mode=OneWay}"
Severity="Success" />
<StackPanel
Grid.Row="1"
Margin="0,0,12,0"
HorizontalAlignment="Right"
Orientation="Horizontal"
Spacing="8">
<Button
x:Name="DocsBtn"
x:Uid="DocsBtn"
Click="DocsBtn_Click"
Style="{StaticResource FlyoutButtonStyle}">
<ToolTipService.ToolTip>
<TextBlock x:Uid="DocsTooltip"/>
</ToolTipService.ToolTip>
<FontIcon FontSize="14" Glyph="&#xE130;" />
</Button>
<Button
x:Name="ReportBugBtn"
x:Uid="BugReportBtn"
Click="ReportBugBtn_Click"
Style="{StaticResource FlyoutButtonStyle}">
<ToolTipService.ToolTip>
<TextBlock x:Uid="BugReportTooltip"/>
</ToolTipService.ToolTip>
<FontIcon FontSize="14" Glyph="&#xebe8;" />
</Button>
<Button
x:Name="SettingsBtn"
Padding="8"
x:Uid="SettingsBtn"
Click="SettingsBtn_Click"
Style="{StaticResource FlyoutButtonStyle}">
<ToolTipService.ToolTip>
<TextBlock x:Uid="SettingsTooltip"/>
</ToolTipService.ToolTip>
<AnimatedIcon x:Name="SearchAnimatedIcon">
<AnimatedIcon.Source>
<animatedVisuals:AnimatedSettingsVisualSource />
</AnimatedIcon.Source>
<AnimatedIcon.FallbackIconSource>
<SymbolIconSource Symbol="Setting" />
</AnimatedIcon.FallbackIconSource>
</AnimatedIcon>
</Button>
<!--<AppBarSeparator />
<Button
x:Name="QuitBtn"
Style="{StaticResource FlyoutButtonStyle}"
ToolTipService.ToolTip="Quit"
Click="QuitButton_Click">
<FontIcon FontSize="14" Glyph="&#xe894;" />
</Button>-->
</StackPanel>
</Grid>
</Grid>
</Page>

View File

@ -0,0 +1,140 @@
// 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 global::Windows.System;
using interop;
using Microsoft.PowerToys.Settings.UI.Controls;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.PowerToys.Telemetry;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media.Animation;
namespace Microsoft.PowerToys.Settings.UI.Flyout
{
public sealed partial class LaunchPage : Page
{
private LauncherViewModel ViewModel { get; set; }
public LaunchPage()
{
this.InitializeComponent();
var settingsUtils = new SettingsUtils();
ViewModel = new LauncherViewModel(SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), Views.ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
}
private void ModuleButton_Click(object sender, RoutedEventArgs e)
{
FlyoutMenuButton selectedModuleBtn = sender as FlyoutMenuButton;
bool moduleRun = true;
switch ((string)selectedModuleBtn.Tag)
{
case "ColorPicker": // Launch ColorPicker
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShowColorPickerSharedEvent()))
{
eventHandle.Set();
}
break;
case "FancyZones": // Launch FancyZones Editor
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.FZEToggleEvent()))
{
eventHandle.Set();
}
break;
case "Hosts": // Launch Hosts
{
bool launchAdmin = SettingsRepository<HostsSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.LaunchAdministrator;
var actionName = "Launch";
if (!App.IsElevated && launchAdmin)
{
actionName = "LaunchAdministrator";
}
Views.ShellPage.SendDefaultIPCMessage("{\"action\":{\"Hosts\":{\"action_name\":\"" + actionName + "\", \"value\":\"\"}}}");
}
break;
case "MeasureTool": // Launch Screen Ruler
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.MeasureToolTriggerEvent()))
{
eventHandle.Set();
}
break;
case "PowerLauncher": // Launch Run
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.PowerLauncherSharedEvent()))
{
eventHandle.Set();
}
break;
case "PowerOCR": // Launch Text Extractor
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShowPowerOCRSharedEvent()))
{
eventHandle.Set();
}
break;
case "ShortcutGuide": // Launch Shortcut Guide
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShortcutGuideTriggerEvent()))
{
eventHandle.Set();
}
break;
default:
moduleRun = false;
break;
}
if (moduleRun)
{
PowerToysTelemetry.Log.WriteEvent(new TrayFlyoutModuleRunEvent() { ModuleName = (string)selectedModuleBtn.Tag });
}
}
private void SettingsBtn_Click(object sender, RoutedEventArgs e)
{
App.OpenSettingsWindow(null, true);
}
private async void DocsBtn_Click(object sender, RoutedEventArgs e)
{
await Launcher.LaunchUriAsync(new Uri("https://aka.ms/PowerToysOverview"));
}
private void AllAppButton_Click(object sender, RoutedEventArgs e)
{
Frame.Navigate(typeof(AppsListPage), null, new SlideNavigationTransitionInfo() { Effect = SlideNavigationTransitionEffect.FromRight });
}
private void QuitButton_Click(object sender, RoutedEventArgs e)
{
ViewModel.KillRunner();
this.DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
{
Application.Current.Exit();
});
}
private void ReportBugBtn_Click(object sender, RoutedEventArgs e)
{
ViewModel.StartBugReport();
}
}
}

View File

@ -0,0 +1,14 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.Flyout.ShellPage"
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:local="using:Microsoft.PowerToys.Settings.UI.Flyout"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Loaded="Page_Loaded"
mc:Ignorable="d">
<Grid>
<Frame x:Name="ContentFrame" />
</Grid>
</Page>

View File

@ -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 Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media.Animation;
namespace Microsoft.PowerToys.Settings.UI.Flyout
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class ShellPage : Page
{
public ShellPage()
{
this.InitializeComponent();
}
internal void SwitchToLaunchPage()
{
ContentFrame.Navigate(typeof(LaunchPage), null, new SuppressNavigationTransitionInfo());
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
SwitchToLaunchPage();
}
}
}

View File

@ -0,0 +1,32 @@
<winuiex:WindowEx
x:Class="Microsoft.PowerToys.Settings.UI.FlyoutWindow"
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:flyout="using:Microsoft.PowerToys.Settings.UI.Flyout"
xmlns:local="using:Microsoft.PowerToys.Settings.UI"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:winuiex="using:WinUIEx"
Title="PowerToys Settings"
IsAlwaysOnTop="True"
IsMaximizable="False"
IsMinimizable="False"
IsResizable="False"
IsShownInSwitchers="False"
IsTitleBarVisible="False"
mc:Ignorable="d">
<winuiex:WindowEx.Backdrop>
<winuiex:AcrylicSystemBackdrop
DarkFallbackColor="#1c1c1c"
DarkLuminosityOpacity="0.96"
DarkTintColor="#202020"
DarkTintOpacity="0.5"
LightFallbackColor="#EEEEEE"
LightLuminosityOpacity="0.90"
LightTintColor="#F3F3F3"
LightTintOpacity="0" />
</winuiex:WindowEx.Backdrop>
<Grid>
<flyout:ShellPage x:Name="FlyoutShellPage"/>
</Grid>
</winuiex:WindowEx>

View File

@ -0,0 +1,51 @@
// 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 Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events;
using Microsoft.PowerToys.Settings.UI.ViewModels.Flyout;
using Microsoft.PowerToys.Telemetry;
using Microsoft.UI;
using Microsoft.UI.Windowing;
using WinUIEx;
namespace Microsoft.PowerToys.Settings.UI
{
/// <summary>
/// An empty window that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class FlyoutWindow : WindowEx
{
private const int WindowWidth = 386;
private const int WindowHeight = 486;
private const int WindowMargin = 12;
public FlyoutViewModel ViewModel { get; set; }
public FlyoutWindow()
{
this.InitializeComponent();
this.Activated += FlyoutWindow_Activated;
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
WindowId windowId = Win32Interop.GetWindowIdFromWindow(hwnd);
DisplayArea displayArea = DisplayArea.GetFromWindowId(windowId, DisplayAreaFallback.Nearest);
double dpiScale = (float)this.GetDpiForWindow() / 96;
double x = displayArea.WorkArea.Width - (dpiScale * (WindowWidth + WindowMargin));
double y = displayArea.WorkArea.Height - (dpiScale * (WindowHeight + WindowMargin));
this.MoveAndResize(x, y, WindowWidth, WindowHeight);
ViewModel = new FlyoutViewModel();
}
private void FlyoutWindow_Activated(object sender, Microsoft.UI.Xaml.WindowActivatedEventArgs args)
{
PowerToysTelemetry.Log.WriteEvent(new TrayFlyoutActivatedEvent());
if (args.WindowActivationState == Microsoft.UI.Xaml.WindowActivationState.Deactivated)
{
if (ViewModel.CanHide)
{
FlyoutShellPage.SwitchToLaunchPage();
this.Hide();
}
}
}
}
}

View File

@ -0,0 +1,12 @@
// 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.
// An interface so that pages can define refresh method to refresh their view models.
namespace Microsoft.PowerToys.Settings.UI.Helpers
{
public interface IRefreshablePage
{
void RefreshEnabledState();
}
}

View File

@ -51,6 +51,9 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
[DllImport("user32.dll")]
public static extern bool AllowSetForegroundWindow(int dwProcessId);
[System.Runtime.InteropServices.DllImport("User32.dll")]
public static extern bool SetForegroundWindow(IntPtr handle);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr LoadLibrary(string dllToLoad);

View File

@ -45,5 +45,13 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
{
}
}
public static void BecomeForegroundWindow(IntPtr hWnd)
{
NativeKeyboardHelper.INPUT input = new NativeKeyboardHelper.INPUT { type = NativeKeyboardHelper.INPUTTYPE.INPUT_MOUSE, data = { } };
NativeKeyboardHelper.INPUT[] inputs = new NativeKeyboardHelper.INPUT[] { input };
_ = NativeMethods.SendInput(1, inputs, NativeKeyboardHelper.INPUT.Size);
NativeMethods.SetForegroundWindow(hWnd);
}
}
}

View File

@ -6,6 +6,7 @@ using System;
using ManagedCommon;
using Microsoft.PowerLauncher.Telemetry;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.PowerToys.Telemetry;
@ -14,6 +15,7 @@ using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Windows.ApplicationModel.Resources;
using Windows.Data.Json;
using WinUIEx;
namespace Microsoft.PowerToys.Settings.UI
{
@ -73,6 +75,90 @@ namespace Microsoft.PowerToys.Settings.UI
App.GetTwoWayIPCManager()?.Send(msg);
});
// open main window
ShellPage.SetOpenMainWindowCallback(() =>
{
this.DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
App.OpenSettingsWindow(typeof(GeneralPage)));
});
// open main window
ShellPage.SetUpdatingGeneralSettingsCallback((string module, bool isEnabled) =>
{
SettingsRepository<GeneralSettings> repository = SettingsRepository<GeneralSettings>.GetInstance(new SettingsUtils());
GeneralSettings generalSettingsConfig = repository.SettingsConfig;
bool needToUpdate = false;
switch (module)
{
case "AlwaysOnTop":
needToUpdate = generalSettingsConfig.Enabled.AlwaysOnTop != isEnabled;
generalSettingsConfig.Enabled.AlwaysOnTop = isEnabled; break;
case "Awake":
needToUpdate = generalSettingsConfig.Enabled.Awake != isEnabled;
generalSettingsConfig.Enabled.Awake = isEnabled; break;
case "ColorPicker":
needToUpdate = generalSettingsConfig.Enabled.ColorPicker != isEnabled;
generalSettingsConfig.Enabled.ColorPicker = isEnabled; break;
case "FancyZones":
needToUpdate = generalSettingsConfig.Enabled.FancyZones != isEnabled;
generalSettingsConfig.Enabled.FancyZones = isEnabled; break;
case "FileLocksmith":
needToUpdate = generalSettingsConfig.Enabled.FileLocksmith != isEnabled;
generalSettingsConfig.Enabled.FileLocksmith = isEnabled; break;
case "FindMyMouse":
needToUpdate = generalSettingsConfig.Enabled.FindMyMouse != isEnabled;
generalSettingsConfig.Enabled.FindMyMouse = isEnabled; break;
case "Hosts":
needToUpdate = generalSettingsConfig.Enabled.Hosts != isEnabled;
generalSettingsConfig.Enabled.Hosts = isEnabled; break;
case "ImageResizer":
needToUpdate = generalSettingsConfig.Enabled.ImageResizer != isEnabled;
generalSettingsConfig.Enabled.ImageResizer = isEnabled; break;
case "KeyboardManager":
needToUpdate = generalSettingsConfig.Enabled.KeyboardManager != isEnabled;
generalSettingsConfig.Enabled.KeyboardManager = isEnabled; break;
case "MouseHighlighter":
needToUpdate = generalSettingsConfig.Enabled.MouseHighlighter != isEnabled;
generalSettingsConfig.Enabled.MouseHighlighter = isEnabled; break;
case "MousePointerCrosshairs":
needToUpdate = generalSettingsConfig.Enabled.MousePointerCrosshairs != isEnabled;
generalSettingsConfig.Enabled.MousePointerCrosshairs = isEnabled; break;
case "PowerRename":
needToUpdate = generalSettingsConfig.Enabled.PowerRename != isEnabled;
generalSettingsConfig.Enabled.PowerRename = isEnabled; break;
case "PowerLauncher":
needToUpdate = generalSettingsConfig.Enabled.PowerLauncher != isEnabled;
generalSettingsConfig.Enabled.PowerLauncher = isEnabled; break;
case "PowerAccent":
needToUpdate = generalSettingsConfig.Enabled.PowerAccent != isEnabled;
generalSettingsConfig.Enabled.PowerAccent = isEnabled; break;
case "MeasureTool":
needToUpdate = generalSettingsConfig.Enabled.MeasureTool != isEnabled;
generalSettingsConfig.Enabled.MeasureTool = isEnabled; break;
case "ShortcutGuide":
needToUpdate = generalSettingsConfig.Enabled.ShortcutGuide != isEnabled;
generalSettingsConfig.Enabled.ShortcutGuide = isEnabled; break;
case "PowerOCR":
needToUpdate = generalSettingsConfig.Enabled.PowerOCR != isEnabled;
generalSettingsConfig.Enabled.PowerOCR = isEnabled; break;
case "VideoConference":
needToUpdate = generalSettingsConfig.Enabled.VideoConference != isEnabled;
generalSettingsConfig.Enabled.VideoConference = isEnabled; break;
}
if (needToUpdate)
{
var outgoing = new OutGoingGeneralSettings(generalSettingsConfig);
this.DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
{
ShellPage.SendDefaultIPCMessage(outgoing.ToString());
ShellPage.ShellHandler?.SignalGeneralDataUpdate();
});
}
return needToUpdate;
});
// open oobe
ShellPage.SetOpenOobeCallback(() =>
{
@ -84,6 +170,39 @@ namespace Microsoft.PowerToys.Settings.UI
App.GetOobeWindow().Activate();
});
// open flyout
ShellPage.SetOpenFlyoutCallback(() =>
{
this.DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
{
if (App.GetFlyoutWindow() == null)
{
App.SetFlyoutWindow(new FlyoutWindow());
}
FlyoutWindow flyout = App.GetFlyoutWindow();
flyout.Activate();
// https://github.com/microsoft/microsoft-ui-xaml/issues/7595 - Activate doesn't bring window to the foreground
// Need to call SetForegroundWindow to actually gain focus.
Utils.BecomeForegroundWindow(flyout.GetWindowHandle());
});
});
// disable flyout hiding
ShellPage.SetDisableFlyoutHidingCallback(() =>
{
this.DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
{
if (App.GetFlyoutWindow() == null)
{
App.SetFlyoutWindow(new FlyoutWindow());
}
App.GetFlyoutWindow().ViewModel.DisableHiding();
});
});
this.InitializeComponent();
// receive IPC Message
@ -140,5 +259,10 @@ namespace Microsoft.PowerToys.Settings.UI
NativeMethods.ShowWindow(hWnd, NativeMethods.SW_HIDE);
}
}
internal void EnsurePageIsSelected()
{
ShellPage.EnsurePageIsSelected();
}
}
}

View File

@ -59,6 +59,14 @@
<None Remove="Controls\ColorFormatEditor.xaml" />
</ItemGroup>
<ItemGroup>
<None Remove="FlyoutWindow.xaml" />
<None Remove="Flyout\AppsListPage.xaml" />
<None Remove="Controls\FlyoutMenuButton\FlyoutMenuButton.xaml" />
<None Remove="Flyout\LaunchPage.xaml" />
<None Remove="Flyout\ShellPage.xaml" />
</ItemGroup>
<ItemGroup>
<Content Include="Assets\SplashScreen.scale-200.png" />
<Content Include="Assets\LockScreenLogo.scale-200.png" />
@ -74,6 +82,7 @@
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.0.0" />
<PackageReference Include="CommunityToolkit.WinUI.UI" Version="7.1.2" />
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls" Version="7.1.2" />
<PackageReference Include="WinUIEx" Version="1.8.0" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.2.221116.1" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.755" />
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
@ -92,9 +101,24 @@
<ProjectReference Include="..\Settings.UI.Library\Settings.UI.Library.csproj" />
</ItemGroup>
<ItemGroup>
<Page Update="FlyoutWindow.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Flyout\LaunchPage.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Flyout\ShellPage.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Controls\ColorFormatEditor.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Flyout\AppsListPage.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Update="Flyout\Controls\FlyoutMenuButton.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<None Update="icon.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>

View File

@ -101,5 +101,13 @@ namespace Microsoft.PowerToys.Settings.UI.Services
private static void Frame_NavigationFailed(object sender, NavigationFailedEventArgs e) => NavigationFailed?.Invoke(sender, e);
private static void Frame_Navigated(object sender, NavigationEventArgs e) => Navigated?.Invoke(sender, e);
internal static void EnsurePageIsSelected(Type pageType)
{
if (Frame.Content == null)
{
Frame.Navigate(pageType);
}
}
}
}

View File

@ -895,7 +895,7 @@
<value>Remove</value>
<comment>Removes a user defined setting group for Image Resizer</comment>
</data>
<data name="RemoveItem.Text" xml:space="preserve">
<data name="RemoveItem.Text" xml:space="preserve">
<value>Delete</value>
</data>
<data name="ImageResizer_Image.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
@ -2693,7 +2693,7 @@ Activate by holding the key for the character you want to add an accent to, then
<data name="QuickAccent_StartSelectionFromTheLeft_Indicator.Header" xml:space="preserve">
<value>Start selection from the left</value>
</data>
<data name="QuickAccent_StartSelectionFromTheLeft_Indicator.Description" xml:space="preserve">
<data name="QuickAccent_StartSelectionFromTheLeft_Indicator.Description" xml:space="preserve">
<value>Start selection from the leftmost character for all activation keys, including left and right arrows</value>
</data>
<data name="QuickAccent_DisableFullscreen.Header" xml:space="preserve">
@ -2888,4 +2888,47 @@ Activate by holding the key for the character you want to add an accent to, then
<data name="TextExtractor_Languages.Header" xml:space="preserve">
<value>Preferred language</value>
</data>
</root>
<data name="AllAppsTxt.Text" xml:space="preserve">
<value>All apps</value>
</data>
<data name="BackBtn.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Back</value>
</data>
<data name="BackLabel.Text" xml:space="preserve">
<value>Back</value>
</data>
<data name="BugReportBtn.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Bug report</value>
</data>
<data name="BugReportTooltip.Text" xml:space="preserve">
<value>Bug report</value>
</data>
<data name="DocsBtn.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Documentation</value>
</data>
<data name="DocsTooltip.Text" xml:space="preserve">
<value>Documentation</value>
</data>
<data name="FZEditorString" xml:space="preserve">
<value>FancyZones Editor</value>
<comment>Do not localize this string</comment>
</data>
<data name="MoreBtn.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>More</value>
</data>
<data name="MoreLabel.Text" xml:space="preserve">
<value>More</value>
</data>
<data name="SettingsBtn.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Settings</value>
</data>
<data name="SettingsTooltip.Text" xml:space="preserve">
<value>Settings</value>
</data>
<data name="ShortcutsTxt.Text" xml:space="preserve">
<value>Shortcuts</value>
</data>
<data name="UpdateAvailable.Title" xml:space="preserve">
<value>Update available</value>
</data>
</root>

View File

@ -1,35 +1,15 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush
x:Key="SubtleButtonBackground"
Color="{ThemeResource SubtleFillColorTransparent}" />
<SolidColorBrush
x:Key="SubtleButtonBackgroundPointerOver"
Color="{ThemeResource SubtleFillColorSecondary}" />
<SolidColorBrush
x:Key="SubtleButtonBackgroundPressed"
Color="{ThemeResource SubtleFillColorTertiary}" />
<SolidColorBrush
x:Key="SubtleButtonBackgroundDisabled"
Color="{ThemeResource SubtleFillColorTransparent}" />
<SolidColorBrush
x:Key="SubtleButtonForeground"
Color="{ThemeResource TextFillColorPrimary}" />
<SolidColorBrush
x:Key="SubtleButtonForegroundPointerOver"
Color="{ThemeResource TextFillColorPrimary}" />
<SolidColorBrush
x:Key="SubtleButtonForegroundPressed"
Color="{ThemeResource TextFillColorSecondary}" />
<SolidColorBrush
x:Key="SubtleButtonForegroundDisabled"
Color="{ThemeResource TextFillColorDisabled}" />
<SolidColorBrush x:Key="SubtleButtonBackground" Color="{ThemeResource SubtleFillColorTransparent}" />
<SolidColorBrush x:Key="SubtleButtonBackgroundPointerOver" Color="{ThemeResource SubtleFillColorSecondary}" />
<SolidColorBrush x:Key="SubtleButtonBackgroundPressed" Color="{ThemeResource SubtleFillColorTertiary}" />
<SolidColorBrush x:Key="SubtleButtonBackgroundDisabled" Color="{ThemeResource SubtleFillColorTransparent}" />
<SolidColorBrush x:Key="SubtleButtonForeground" Color="{ThemeResource TextFillColorPrimary}" />
<SolidColorBrush x:Key="SubtleButtonForegroundPointerOver" Color="{ThemeResource TextFillColorPrimary}" />
<SolidColorBrush x:Key="SubtleButtonForegroundPressed" Color="{ThemeResource TextFillColorSecondary}" />
<SolidColorBrush x:Key="SubtleButtonForegroundDisabled" Color="{ThemeResource TextFillColorDisabled}" />
<Style
x:Key="SubtleButtonStyle"
TargetType="Button">
<Style x:Key="SubtleButtonStyle" TargetType="Button">
<Setter Property="Background" Value="{ThemeResource SubtleButtonBackground}" />
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
<Setter Property="Foreground" Value="{ThemeResource SubtleButtonForeground}" />
@ -73,19 +53,11 @@
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{ThemeResource SubtleButtonBackgroundPointerOver}" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{ThemeResource SubtleButtonForegroundPointerOver}" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
@ -95,19 +67,11 @@
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{ThemeResource SubtleButtonBackgroundPressed}" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{ThemeResource SubtleButtonForegroundPressed}" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPressed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
@ -117,19 +81,11 @@
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{ThemeResource SubtleButtonBackgroundDisabled}" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{ThemeResource SubtleButtonForegroundDisabled}" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
@ -145,13 +101,9 @@
</Setter>
</Style>
<Style
x:Key="HyperlinkButtonStyle"
TargetType="HyperlinkButton" />
<Style x:Key="HyperlinkButtonStyle" TargetType="HyperlinkButton" />
<Style
x:Key="TextButtonStyle"
TargetType="ButtonBase">
<Style x:Key="TextButtonStyle" TargetType="ButtonBase">
<Setter Property="Background" Value="{ThemeResource HyperlinkButtonBackground}" />
<Setter Property="Foreground" Value="{ThemeResource HyperlinkButtonForeground}" />
<Setter Property="MinWidth" Value="0" />
@ -165,99 +117,686 @@
Margin="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"
CornerRadius="4">
<ContentPresenter
x:Name="Text"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
FontWeight="SemiBold" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="Text"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{ThemeResource HyperlinkButtonForegroundPointerOver}" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="Text"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{ThemeResource HyperlinkButtonBackgroundPointerOver}" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="Text"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{ThemeResource HyperlinkButtonBorderBrushPointerOver}" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonBorderBrushPointerOver}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="Text"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{ThemeResource HyperlinkButtonForegroundPressed}" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonForegroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="Text"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{ThemeResource HyperlinkButtonBackgroundPressed}" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="Text"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{ThemeResource HyperlinkButtonBorderBrushPressed}" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonBorderBrushPressed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="Text"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{ThemeResource HyperlinkButtonForegroundDisabled}" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="Text"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{ThemeResource HyperlinkButtonBackgroundDisabled}" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonBackgroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames
Storyboard.TargetName="Text"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame
KeyTime="0"
Value="{ThemeResource HyperlinkButtonBorderBrushDisabled}" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonBorderBrushDisabled}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter
x:Name="Text"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
FontWeight="SemiBold" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="RightAlignedCompactToggleSwitchStyle"
BasedOn="{StaticResource DefaultToggleSwitchStyle}"
TargetType="ToggleSwitch">
<Style.Setters>
<Setter Property="MinWidth" Value="0" />
<Setter Property="Height" Value="36" />
<Setter Property="HorizontalContentAlignment" Value="Right" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleSwitch">
<Grid VerticalAlignment="Center"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="Stroke">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchStrokeOff}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchFillOff}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchKnobFillOff}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchKnobFillOn}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchFillOn}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Stroke">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchStrokeOn}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchAreaGrid"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchContainerBackground}" />
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Width">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="12" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Height">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="12" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Width">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="12" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Height">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="12" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="{ThemeResource ToggleSwitchStrokeOffPointerOver}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="{ThemeResource ToggleSwitchFillOffPointerOver}" />
</ColorAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchKnobFillOffPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchKnobFillOnPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchFillOnPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Stroke">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchStrokeOnPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="SwitchAreaGrid"
Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="{ThemeResource ToggleSwitchContainerBackgroundPointerOver}" />
</ColorAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Width">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="14" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Height">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="14" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Width">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="14" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Height">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="14" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<VisualState.Setters>
<Setter Target="SwitchKnobOn.HorizontalAlignment" Value="Right" />
<Setter Target="SwitchKnobOn.Margin" Value="0,0,3,0" />
<Setter Target="SwitchKnobOff.HorizontalAlignment" Value="Left" />
<Setter Target="SwitchKnobOff.Margin" Value="3,0,0,0" />
</VisualState.Setters>
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="{ThemeResource ToggleSwitchStrokeOffPressed}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="{ThemeResource ToggleSwitchFillOffPressed}" />
</ColorAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchFillOnPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Stroke">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchStrokeOnPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchKnobFillOffPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchKnobFillOnPressed}" />
</ObjectAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="SwitchAreaGrid"
Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="{ThemeResource ToggleSwitchContainerBackgroundPressed}" />
</ColorAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Width">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="17" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Height">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="14" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Width">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="17" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Height">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="14" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchHeaderForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OffContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchContentForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OnContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchContentForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="{ThemeResource ToggleSwitchStrokeOffDisabled}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="{ThemeResource ToggleSwitchFillOffDisabled}" />
</ColorAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchFillOnDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Stroke">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchStrokeOnDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchKnobFillOffDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchKnobFillOnDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="SwitchAreaGrid"
Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="{ThemeResource ToggleSwitchContainerBackgroundDisabled}" />
</ColorAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Width">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlNormalAnimationDuration}"
Value="12" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Height">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlNormalAnimationDuration}"
Value="12" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Width">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlNormalAnimationDuration}"
Value="12" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Height">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlNormalAnimationDuration}"
Value="12" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ToggleStates">
<VisualStateGroup.Transitions>
<VisualTransition x:Name="DraggingToOnTransition"
GeneratedDuration="0"
From="Dragging"
To="On">
<Storyboard>
<RepositionThemeAnimation FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobCurrentToOnOffset}"
TargetName="SwitchKnob" />
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
<VisualTransition x:Name="OnToDraggingTransition"
GeneratedDuration="0"
From="On"
To="Dragging">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="0"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="0"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="0"
Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
<VisualTransition x:Name="DraggingToOffTransition"
GeneratedDuration="0"
From="Dragging"
To="Off">
<Storyboard>
<RepositionThemeAnimation FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobCurrentToOffOffset}"
TargetName="SwitchKnob" />
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
<VisualTransition x:Name="OnToOffTransition"
GeneratedDuration="0"
From="On"
To="Off">
<Storyboard>
<RepositionThemeAnimation FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobOnToOffOffset}"
TargetName="SwitchKnob" />
</Storyboard>
</VisualTransition>
<VisualTransition x:Name="OffToOnTransition"
GeneratedDuration="0"
From="Off"
To="On">
<Storyboard>
<RepositionThemeAnimation FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobOffToOnOffset}"
TargetName="SwitchKnob" />
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="Dragging" />
<VisualState x:Name="Off" />
<VisualState x:Name="On">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="KnobTranslateTransform"
Storyboard.TargetProperty="X"
To="20"
Duration="0" />
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ContentStates">
<VisualState x:Name="OffContent">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="OffContentPresenter"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OffContentPresenter"
Storyboard.TargetProperty="IsHitTestVisible">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<x:Boolean>True</x:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="OnContent">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="OnContentPresenter"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OnContentPresenter"
Storyboard.TargetProperty="IsHitTestVisible">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<x:Boolean>True</x:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="HeaderContentPresenter"
Grid.Row="0"
Margin="{ThemeResource ToggleSwitchTopHeaderMargin}"
VerticalAlignment="Top"
AutomationProperties.AccessibilityView="Raw"
x:DeferLoadStrategy="Lazy"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
Foreground="{ThemeResource ToggleSwitchHeaderForeground}"
IsHitTestVisible="False"
TextWrapping="Wrap"
Visibility="Collapsed" />
<Grid Grid.Row="1"
HorizontalAlignment="Right"
VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="{ThemeResource ToggleSwitchPreContentMargin}" />
<RowDefinition Height="Auto" />
<RowDefinition Height="{ThemeResource ToggleSwitchPostContentMargin}" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="12"
MaxWidth="12" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid x:Name="SwitchAreaGrid"
Grid.RowSpan="3"
Grid.ColumnSpan="3"
Margin="0,5"
Background="{ThemeResource ToggleSwitchContainerBackground}"
Control.IsTemplateFocusTarget="True"
CornerRadius="{TemplateBinding CornerRadius}" />
<ContentPresenter x:Name="OffContentPresenter"
Grid.RowSpan="3"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
AutomationProperties.AccessibilityView="Raw"
Content="{TemplateBinding OffContent}"
ContentTemplate="{TemplateBinding OffContentTemplate}"
Foreground="{TemplateBinding Foreground}"
IsHitTestVisible="False"
Opacity="0" />
<ContentPresenter x:Name="OnContentPresenter"
Grid.RowSpan="3"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
AutomationProperties.AccessibilityView="Raw"
Content="{TemplateBinding OnContent}"
ContentTemplate="{TemplateBinding OnContentTemplate}"
Foreground="{TemplateBinding Foreground}"
IsHitTestVisible="False"
Opacity="0" />
<Rectangle x:Name="OuterBorder"
Grid.Row="1"
Grid.Column="2"
Width="40"
Height="20"
Fill="{ThemeResource ToggleSwitchFillOff}"
RadiusX="10"
RadiusY="10"
Stroke="{ThemeResource ToggleSwitchStrokeOff}"
StrokeThickness="{ThemeResource ToggleSwitchOuterBorderStrokeThickness}" />
<Rectangle x:Name="SwitchKnobBounds"
Grid.Row="1"
Grid.Column="2"
Width="40"
Height="20"
Fill="{ThemeResource ToggleSwitchFillOn}"
Opacity="0"
RadiusX="10"
RadiusY="10"
Stroke="{ThemeResource ToggleSwitchStrokeOn}"
StrokeThickness="{ThemeResource ToggleSwitchOnStrokeThickness}" />
<Grid x:Name="SwitchKnob"
Grid.Row="1"
Grid.Column="2"
Width="20"
Height="20"
HorizontalAlignment="Left">
<Border x:Name="SwitchKnobOn"
Width="12"
Height="12"
Margin="0,0,3,0"
HorizontalAlignment="Right"
Background="{ThemeResource ToggleSwitchKnobFillOn}"
BackgroundSizing="OuterBorderEdge"
BorderBrush="{ThemeResource ToggleSwitchKnobStrokeOn}"
CornerRadius="7"
Opacity="0"
RenderTransformOrigin="0.5, 0.5">
<Border.RenderTransform>
<CompositeTransform />
</Border.RenderTransform>
</Border>
<Rectangle x:Name="SwitchKnobOff"
Width="12"
Height="12"
Margin="3,0,0,0"
HorizontalAlignment="Left"
Fill="{ThemeResource ToggleSwitchKnobFillOff}"
RadiusX="7"
RadiusY="7"
RenderTransformOrigin="0.5, 0.5">
<Rectangle.RenderTransform>
<CompositeTransform />
</Rectangle.RenderTransform>
</Rectangle>
<Grid.RenderTransform>
<TranslateTransform x:Name="KnobTranslateTransform" />
</Grid.RenderTransform>
</Grid>
<Thumb x:Name="SwitchThumb"
Grid.RowSpan="3"
Grid.ColumnSpan="3"
AutomationProperties.AccessibilityView="Raw">
<Thumb.Template>
<ControlTemplate TargetType="Thumb">
<Rectangle Fill="Transparent" />
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</ResourceDictionary>

View File

@ -18,10 +18,15 @@
</Style>
<x:Double x:Key="SecondaryTextFontSize">12</x:Double>
<Style
x:Key="SecondaryTextStyle"
TargetType="TextBlock">
<Style x:Key="SecondaryTextStyle" TargetType="TextBlock">
<Setter Property="FontSize" Value="{StaticResource SecondaryTextFontSize}" />
<Setter Property="Foreground" Value="{ThemeResource TextFillColorSecondaryBrush}" />
</Style>
<x:Double x:Key="HeaderTextFontSize">12</x:Double>
<Style x:Key="HeaderTextStyle" TargetType="TextBlock">
<Setter Property="FontSize" Value="{StaticResource HeaderTextFontSize}"/>
<Setter Property="Foreground" Value="{ThemeResource TextFillColorSecondaryBrush}"/>
<Setter Property="FontWeight" Value="Bold" />
</Style>
</ResourceDictionary>

View File

@ -1,9 +1,8 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ms-appx:///Controls/SettingsGroup/SettingsGroup.xaml" />
<ResourceDictionary Source="ms-appx:///Controls/IsEnabledTextBlock/IsEnabledTextBlock.xaml" />
<ResourceDictionary Source="ms-appx:///Controls/FlyoutMenuButton/FlyoutMenuButton.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

View File

@ -41,6 +41,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
GeneralSettingsConfig = settingsRepository.SettingsConfig;
InitializeEnabledValue();
// To obtain the settings configurations of AlwaysOnTop.
if (moduleSettingsRepository == null)
{
@ -49,18 +51,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
Settings = moduleSettingsRepository.SettingsConfig;
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredAlwaysOnTopEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.AlwaysOnTop;
}
_hotkey = Settings.Properties.Hotkey.Value;
_frameEnabled = Settings.Properties.FrameEnabled.Value;
_frameThickness = Settings.Properties.FrameThickness.Value;
@ -76,6 +66,21 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
SendConfigMSG = ipcMSGCallBackFunc;
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredAlwaysOnTopEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.AlwaysOnTop;
}
}
public bool IsEnabled
{
get => _isEnabled;
@ -274,6 +279,12 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
SettingsUtils.SaveSettings(Settings.ToJsonString(), AlwaysOnTopSettings.ModuleName);
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsEnabled));
}
private GpoRuleConfigured _enabledGpoRuleConfiguration;
private bool _enabledStateIsGPOConfigured;
private bool _isEnabled;

View File

@ -37,6 +37,19 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
Settings = moduleSettingsRepository.SettingsConfig;
InitializeEnabledValue();
_keepDisplayOn = Settings.Properties.KeepDisplayOn;
_mode = Settings.Properties.Mode;
_hours = Settings.Properties.Hours;
_minutes = Settings.Properties.Minutes;
// set the callback functions value to hangle outgoing IPC message.
SendConfigMSG = ipcMSGCallBackFunc;
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredAwakeEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
@ -48,14 +61,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
_isEnabled = GeneralSettingsConfig.Enabled.Awake;
}
_keepDisplayOn = Settings.Properties.KeepDisplayOn;
_mode = Settings.Properties.Mode;
_hours = Settings.Properties.Hours;
_minutes = Settings.Properties.Minutes;
// set the callback functions value to hangle outgoing IPC message.
SendConfigMSG = ipcMSGCallBackFunc;
}
public bool IsEnabled
@ -179,6 +184,14 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
}
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsEnabled));
OnPropertyChanged(nameof(IsTimeConfigurationEnabled));
OnPropertyChanged(nameof(IsScreenConfigurationPossibleEnabled));
}
private GpoRuleConfigured _enabledGpoRuleConfiguration;
private bool _enabledStateIsGPOConfigured;
private bool _isEnabled;

View File

@ -69,6 +69,21 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
_colorPickerSettings = colorPickerSettingsRepository.SettingsConfig; // used in the unit tests
}
InitializeEnabledValue();
// 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();
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredColorPickerEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
@ -80,16 +95,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
_isEnabled = GeneralSettingsConfig.Enabled.ColorPicker;
}
// 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();
}
public bool IsEnabled
@ -360,6 +365,12 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
JsonSerializer.Serialize(_colorPickerSettings)));
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsEnabled));
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)

View File

@ -116,6 +116,19 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
string numberColor = Settings.Properties.FancyzonesNumberColor.Value;
_zoneNumberColor = !string.IsNullOrEmpty(numberColor) ? numberColor : ConfigDefaults.DefaultFancyzonesNumberColor;
InitializeEnabledValue();
_windows11 = Helper.Windows11();
// Disable setting on windows 10
if (!_windows11 && DisableRoundCornersOnWindowSnap)
{
DisableRoundCornersOnWindowSnap = false;
}
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredFancyZonesEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
@ -127,14 +140,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
_isEnabled = GeneralSettingsConfig.Enabled.FancyZones;
}
_windows11 = Helper.Windows11();
// Disable setting on windows 10
if (!_windows11 && DisableRoundCornersOnWindowSnap)
{
DisableRoundCornersOnWindowSnap = false;
}
}
private GpoRuleConfigured _enabledGpoRuleConfiguration;
@ -883,5 +888,14 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
OnPropertyChanged(propertyName);
SettingsUtils.SaveSettings(Settings.ToJsonString(), GetSettingsSubPath());
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsEnabled));
OnPropertyChanged(nameof(SnapHotkeysCategoryEnabled));
OnPropertyChanged(nameof(QuickSwitchEnabled));
OnPropertyChanged(nameof(WindowSwitchingCategoryEnabled));
}
}
}

View File

@ -24,6 +24,14 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
GeneralSettingsConfig = settingsRepository.SettingsConfig;
InitializeEnabledValue();
// set the callback functions value to hangle outgoing IPC message.
SendConfigMSG = ipcMSGCallBackFunc;
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredFileLocksmithEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
@ -35,9 +43,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
_isFileLocksmithEnabled = GeneralSettingsConfig.Enabled.FileLocksmith;
}
// set the callback functions value to hangle outgoing IPC message.
SendConfigMSG = ipcMSGCallBackFunc;
}
public bool IsFileLocksmithEnabled
@ -77,5 +82,11 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
private GpoRuleConfigured _enabledGpoRuleConfiguration;
private bool _enabledStateIsGPOConfigured;
private bool _isFileLocksmithEnabled;
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsFileLocksmithEnabled));
}
}
}

View File

@ -0,0 +1,163 @@
// 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.Tasks;
using global::PowerToys.GPOWrapper;
using Microsoft.PowerToys.Settings.UI.Flyout;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
using Windows.ApplicationModel.Resources;
namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
public class AllAppsViewModel : Observable
{
public ObservableCollection<FlyoutMenuItem> FlyoutMenuItems { get; set; }
private ISettingsRepository<GeneralSettings> _settingsRepository;
private GeneralSettings generalSettingsConfig;
private Func<string, int> SendConfigMSG { get; }
public AllAppsViewModel(ISettingsRepository<GeneralSettings> settingsRepository, Func<string, int> ipcMSGCallBackFunc)
{
_settingsRepository = settingsRepository;
generalSettingsConfig = settingsRepository.SettingsConfig;
generalSettingsConfig.AddEnabledModuleChangeNotification(ModuleEnabledChangedOnSettingsPage);
FlyoutMenuItems = new ObservableCollection<FlyoutMenuItem>();
ResourceLoader resourceLoader = ResourceLoader.GetForViewIndependentUse();
GpoRuleConfigured gpo;
if ((gpo = GPOWrapper.GetConfiguredAlwaysOnTopEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("AlwaysOnTop/ModuleTitle"), IsEnabled = generalSettingsConfig.Enabled.AlwaysOnTop, Tag = "AlwaysOnTop", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsAlwaysOnTop.png", EnabledChangedCallback = EnabledChangedOnUI });
}
if ((gpo = GPOWrapper.GetConfiguredAwakeEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("Awake/ModuleTitle"), IsEnabled = generalSettingsConfig.Enabled.Awake, Tag = "Awake", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsAwake.png", EnabledChangedCallback = EnabledChangedOnUI });
}
if ((gpo = GPOWrapper.GetConfiguredColorPickerEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("ColorPicker/ModuleTitle"), IsEnabled = generalSettingsConfig.Enabled.ColorPicker, Tag = "ColorPicker", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsColorPicker.png", EnabledChangedCallback = EnabledChangedOnUI });
}
if ((gpo = GPOWrapper.GetConfiguredFancyZonesEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("FancyZones/ModuleTitle"), IsEnabled = generalSettingsConfig.Enabled.FancyZones, Tag = "FancyZones", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsFancyZones.png", EnabledChangedCallback = EnabledChangedOnUI });
}
if ((gpo = GPOWrapper.GetConfiguredFileLocksmithEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("FileLocksmith/ModuleTitle"), IsEnabled = generalSettingsConfig.Enabled.FileLocksmith, Tag = "FileLocksmith", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsFileLocksmith.png", EnabledChangedCallback = EnabledChangedOnUI });
}
if ((gpo = GPOWrapper.GetConfiguredFindMyMouseEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("MouseUtils_FindMyMouse/Header"), IsEnabled = generalSettingsConfig.Enabled.FindMyMouse, Tag = "FindMyMouse", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsFindMyMouse.png", EnabledChangedCallback = EnabledChangedOnUI });
}
if ((gpo = GPOWrapper.GetConfiguredHostsFileEditorEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("Hosts/ModuleTitle"), IsEnabled = generalSettingsConfig.Enabled.Hosts, Tag = "Hosts", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsHosts.png", EnabledChangedCallback = EnabledChangedOnUI });
}
if ((gpo = GPOWrapper.GetConfiguredImageResizerEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("ImageResizer/ModuleTitle"), IsEnabled = generalSettingsConfig.Enabled.ImageResizer, Tag = "ImageResizer", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsImageResizer.png", EnabledChangedCallback = EnabledChangedOnUI });
}
if ((gpo = GPOWrapper.GetConfiguredKeyboardManagerEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("KeyboardManager/ModuleTitle"), IsEnabled = generalSettingsConfig.Enabled.KeyboardManager, Tag = "KeyboardManager", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsKeyboardManager.png", EnabledChangedCallback = EnabledChangedOnUI });
}
if ((gpo = GPOWrapper.GetConfiguredMouseHighlighterEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("MouseUtils_MouseHighlighter/Header"), IsEnabled = generalSettingsConfig.Enabled.MouseHighlighter, Tag = "MouseHighlighter", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsMouseHighlighter.png", EnabledChangedCallback = EnabledChangedOnUI });
}
if ((gpo = GPOWrapper.GetConfiguredMousePointerCrosshairsEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("MouseUtils_MousePointerCrosshairs/Header"), IsEnabled = generalSettingsConfig.Enabled.MousePointerCrosshairs, Tag = "MousePointerCrosshairs", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsMouseCrosshairs.png", EnabledChangedCallback = EnabledChangedOnUI });
}
if ((gpo = GPOWrapper.GetConfiguredPowerRenameEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("PowerRename/ModuleTitle"), IsEnabled = generalSettingsConfig.Enabled.PowerRename, Tag = "PowerRename", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsPowerRename.png", EnabledChangedCallback = EnabledChangedOnUI });
}
if ((gpo = GPOWrapper.GetConfiguredPowerLauncherEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("PowerLauncher/ModuleTitle"), IsEnabled = generalSettingsConfig.Enabled.PowerLauncher, Tag = "PowerLauncher", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsPowerToysRun.png", EnabledChangedCallback = EnabledChangedOnUI });
}
if ((gpo = GPOWrapper.GetConfiguredQuickAccentEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("QuickAccent/ModuleTitle"), IsEnabled = generalSettingsConfig.Enabled.PowerAccent, Tag = "PowerAccent", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsPowerAccent.png", EnabledChangedCallback = EnabledChangedOnUI });
}
if ((gpo = GPOWrapper.GetConfiguredScreenRulerEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("MeasureTool/ModuleTitle"), IsEnabled = generalSettingsConfig.Enabled.MeasureTool, Tag = "MeasureTool", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsScreenRuler.png", EnabledChangedCallback = EnabledChangedOnUI });
}
if ((gpo = GPOWrapper.GetConfiguredShortcutGuideEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("ShortcutGuide/ModuleTitle"), IsEnabled = generalSettingsConfig.Enabled.ShortcutGuide, Tag = "ShortcutGuide", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsShortcutGuide.png", EnabledChangedCallback = EnabledChangedOnUI });
}
if ((gpo = GPOWrapper.GetConfiguredTextExtractorEnabledValue()) != GpoRuleConfigured.Disabled && gpo != GpoRuleConfigured.Enabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem() { Label = resourceLoader.GetString("TextExtractor/ModuleTitle"), IsEnabled = generalSettingsConfig.Enabled.PowerOCR, Tag = "PowerOCR", Icon = "ms-appx:///Assets/FluentIcons/FluentIconsPowerOCR.png", EnabledChangedCallback = EnabledChangedOnUI });
}
// set the callback functions value to hangle outgoing IPC message.
SendConfigMSG = ipcMSGCallBackFunc;
}
private void EnabledChangedOnUI(FlyoutMenuItem flyoutMenuItem)
{
if (Views.ShellPage.UpdateGeneralSettingsCallback(flyoutMenuItem.Tag, flyoutMenuItem.IsEnabled))
{
Views.ShellPage.DisableFlyoutHidingCallback();
}
}
private void ModuleEnabledChangedOnSettingsPage()
{
generalSettingsConfig = _settingsRepository.SettingsConfig;
generalSettingsConfig.AddEnabledModuleChangeNotification(ModuleEnabledChangedOnSettingsPage);
foreach (FlyoutMenuItem item in FlyoutMenuItems)
{
switch (item.Tag)
{
case "AlwaysOnTop": item.IsEnabled = generalSettingsConfig.Enabled.AlwaysOnTop; break;
case "Awake": item.IsEnabled = generalSettingsConfig.Enabled.Awake; break;
case "ColorPicker": item.IsEnabled = generalSettingsConfig.Enabled.ColorPicker; break;
case "FancyZones": item.IsEnabled = generalSettingsConfig.Enabled.FancyZones; break;
case "FileLocksmith": item.IsEnabled = generalSettingsConfig.Enabled.FileLocksmith; break;
case "FindMyMouse": item.IsEnabled = generalSettingsConfig.Enabled.FindMyMouse; break;
case "Hosts": item.IsEnabled = generalSettingsConfig.Enabled.Hosts; break;
case "ImageResizer": item.IsEnabled = generalSettingsConfig.Enabled.ImageResizer; break;
case "KeyboardManager": item.IsEnabled = generalSettingsConfig.Enabled.KeyboardManager; break;
case "MouseHighlighter": item.IsEnabled = generalSettingsConfig.Enabled.MouseHighlighter; break;
case "MousePointerCrosshairs": item.IsEnabled = generalSettingsConfig.Enabled.MousePointerCrosshairs; break;
case "PowerRename": item.IsEnabled = generalSettingsConfig.Enabled.PowerRename; break;
case "PowerLauncher": item.IsEnabled = generalSettingsConfig.Enabled.PowerLauncher; break;
case "PowerAccent": item.IsEnabled = generalSettingsConfig.Enabled.PowerAccent; break;
case "MeasureTool": item.IsEnabled = generalSettingsConfig.Enabled.MeasureTool; break;
case "ShortcutGuide": item.IsEnabled = generalSettingsConfig.Enabled.ShortcutGuide; break;
case "PowerOCR": item.IsEnabled = generalSettingsConfig.Enabled.PowerOCR; break;
case "VideoConference": item.IsEnabled = generalSettingsConfig.Enabled.VideoConference; break;
}
}
}
}
}

View File

@ -0,0 +1,61 @@
// 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.ComponentModel;
using System.Runtime.CompilerServices;
using Microsoft.UI.Xaml;
namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
public class FlyoutMenuItem : INotifyPropertyChanged
{
private bool _visible;
private bool _isEnabled;
public string Label { get; set; }
public string Icon { get; set; }
public string ToolTip { get; set; }
public string Tag { get; set; }
public bool IsEnabled
{
get => _isEnabled;
set
{
if (_isEnabled != value)
{
_isEnabled = value;
OnPropertyChanged();
EnabledChangedCallback?.Invoke(this);
}
}
}
public Action<FlyoutMenuItem> EnabledChangedCallback { get; set; } = null;
public bool Visible
{
get => _visible;
set
{
if (_visible != value)
{
_visible = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

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;
using System.Timers;
namespace Microsoft.PowerToys.Settings.UI.ViewModels.Flyout
{
public class FlyoutViewModel
{
public bool CanHide { get; set; }
private Timer hideTimer;
public FlyoutViewModel()
{
CanHide = true;
hideTimer = new Timer();
hideTimer.Elapsed += HideTimer_Elapsed;
hideTimer.Interval = 1000;
hideTimer.Enabled = false;
}
private void HideTimer_Elapsed(object sender, ElapsedEventArgs e)
{
CanHide = true;
hideTimer.Stop();
}
internal void DisableHiding()
{
CanHide = false;
hideTimer.Stop();
hideTimer.Start();
}
}
}

View File

@ -0,0 +1,166 @@
// 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 global::PowerToys.GPOWrapper;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
using Windows.ApplicationModel.Resources;
namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
public class LauncherViewModel : Observable
{
public bool IsUpdateAvailable { get; set; }
public ObservableCollection<FlyoutMenuItem> FlyoutMenuItems { get; set; }
private GeneralSettings generalSettingsConfig;
private UpdatingSettings updatingSettingsConfig;
private ISettingsRepository<GeneralSettings> _settingsRepository;
private Func<string, int> SendIPCMessage { get; }
public LauncherViewModel(ISettingsRepository<GeneralSettings> settingsRepository, Func<string, int> ipcMSGCallBackFunc)
{
_settingsRepository = settingsRepository;
generalSettingsConfig = settingsRepository.SettingsConfig;
generalSettingsConfig.AddEnabledModuleChangeNotification(ModuleEnabledChanged);
// set the callback functions value to hangle outgoing IPC message.
SendIPCMessage = ipcMSGCallBackFunc;
ResourceLoader resourceLoader = ResourceLoader.GetForViewIndependentUse();
FlyoutMenuItems = new ObservableCollection<FlyoutMenuItem>();
if (GPOWrapper.GetConfiguredColorPickerEnabledValue() != GpoRuleConfigured.Disabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem()
{
Label = resourceLoader.GetString("ColorPicker/ModuleTitle"),
Tag = "ColorPicker",
Visible = generalSettingsConfig.Enabled.ColorPicker,
ToolTip = SettingsRepository<ColorPickerSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut.ToString(),
Icon = "ms-appx:///Assets/FluentIcons/FluentIconsColorPicker.png",
});
}
if (GPOWrapper.GetConfiguredFancyZonesEnabledValue() != GpoRuleConfigured.Disabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem()
{
Label = resourceLoader.GetString("FZEditorString"),
Tag = "FancyZones",
Visible = generalSettingsConfig.Enabled.FancyZones,
ToolTip = SettingsRepository<FancyZonesSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.FancyzonesEditorHotkey.Value.ToString(),
Icon = "ms-appx:///Assets/FluentIcons/FluentIconsFancyZones.png",
});
}
if (GPOWrapper.GetConfiguredHostsFileEditorEnabledValue() != GpoRuleConfigured.Disabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem()
{
Label = resourceLoader.GetString("Hosts/ModuleTitle"),
Tag = "Hosts",
Visible = generalSettingsConfig.Enabled.Hosts,
Icon = "ms-appx:///Assets/FluentIcons/FluentIconsHosts.png",
});
}
if (GPOWrapper.GetConfiguredPowerLauncherEnabledValue() != GpoRuleConfigured.Disabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem()
{
Label = resourceLoader.GetString("PowerLauncher/ModuleTitle"),
Tag = "PowerLauncher",
Visible = generalSettingsConfig.Enabled.PowerLauncher,
ToolTip = SettingsRepository<PowerLauncherSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.OpenPowerLauncher.ToString(),
Icon = "ms-appx:///Assets/FluentIcons/FluentIconsPowerToysRun.png",
});
}
if (GPOWrapper.GetConfiguredTextExtractorEnabledValue() != GpoRuleConfigured.Disabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem()
{
Label = resourceLoader.GetString("TextExtractor/ModuleTitle"),
Tag = "PowerOCR",
Visible = generalSettingsConfig.Enabled.PowerOCR,
ToolTip = SettingsRepository<PowerOcrSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut.ToString(),
Icon = "ms-appx:///Assets/FluentIcons/FluentIconsPowerOcr.png",
});
}
if (GPOWrapper.GetConfiguredScreenRulerEnabledValue() != GpoRuleConfigured.Disabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem()
{
Label = resourceLoader.GetString("MeasureTool/ModuleTitle"),
Tag = "MeasureTool",
Visible = generalSettingsConfig.Enabled.MeasureTool,
ToolTip = SettingsRepository<MeasureToolSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut.ToString(),
Icon = "ms-appx:///Assets/FluentIcons/FluentIconsScreenRuler.png",
});
}
if (GPOWrapper.GetConfiguredShortcutGuideEnabledValue() != GpoRuleConfigured.Disabled)
{
FlyoutMenuItems.Add(new FlyoutMenuItem()
{
Label = resourceLoader.GetString("ShortcutGuide/ModuleTitle"),
Tag = "ShortcutGuide",
Visible = generalSettingsConfig.Enabled.ShortcutGuide,
ToolTip = SettingsRepository<ShortcutGuideSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.OpenShortcutGuide.ToString(),
Icon = "ms-appx:///Assets/FluentIcons/FluentIconsShortcutGuide.png",
});
}
if (updatingSettingsConfig == null)
{
updatingSettingsConfig = new UpdatingSettings();
}
updatingSettingsConfig = UpdatingSettings.LoadSettings();
if (updatingSettingsConfig.State == UpdatingSettings.UpdatingState.ReadyToInstall || updatingSettingsConfig.State == UpdatingSettings.UpdatingState.ReadyToDownload)
{
IsUpdateAvailable = true;
}
else
{
IsUpdateAvailable = false;
}
}
private void ModuleEnabledChanged()
{
generalSettingsConfig = _settingsRepository.SettingsConfig;
generalSettingsConfig.AddEnabledModuleChangeNotification(ModuleEnabledChanged);
foreach (FlyoutMenuItem item in FlyoutMenuItems)
{
switch (item.Tag)
{
case "ColorPicker": item.Visible = generalSettingsConfig.Enabled.ColorPicker; break;
case "FancyZones": item.Visible = generalSettingsConfig.Enabled.FancyZones; break;
case "Hosts": item.Visible = generalSettingsConfig.Enabled.Hosts; break;
case "PowerLauncher": item.Visible = generalSettingsConfig.Enabled.PowerLauncher; break;
case "PowerOCR": item.Visible = generalSettingsConfig.Enabled.PowerOCR; break;
case "MeasureTool": item.Visible = generalSettingsConfig.Enabled.MeasureTool; break;
case "ShortcutGuide": item.Visible = generalSettingsConfig.Enabled.ShortcutGuide; break;
}
}
}
internal void StartBugReport()
{
SendIPCMessage("{\"bugreport\": 0 }");
}
internal void KillRunner()
{
SendIPCMessage("{\"killrunner\": 0 }");
}
}
}

View File

@ -109,6 +109,11 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
Settings = moduleSettingsRepository.SettingsConfig;
SendConfigMSG = ipcMSGCallBackFunc;
_isElevated = isElevated;
InitializeEnabledValue();
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredHostsFileEditorEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
@ -139,5 +144,11 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
OnPropertyChanged(propertyName);
SettingsUtils.SaveSettings(Settings.ToJsonString(), HostsSettings.ModuleName);
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsEnabled));
}
}
}

View File

@ -59,17 +59,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
// set the callback functions value to hangle outgoing IPC message.
SendConfigMSG = ipcMSGCallBackFunc;
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredImageResizerEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.ImageResizer;
}
InitializeEnabledValue();
_advancedSizes = Settings.Properties.ImageresizerSizes.Value;
_jpegQualityLevel = Settings.Properties.ImageresizerJpegQualityLevel.Value;
@ -88,6 +78,21 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
}
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredImageResizerEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.ImageResizer;
}
}
private GpoRuleConfigured _enabledGpoRuleConfiguration;
private bool _enabledStateIsGPOConfigured;
private bool _isEnabled;
@ -420,5 +425,11 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
return $"{namePrefix} {++newSizeCounter}";
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsEnabled));
}
}
}

View File

@ -63,17 +63,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
GeneralSettingsConfig = settingsRepository.SettingsConfig;
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredKeyboardManagerEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.KeyboardManager;
}
InitializeEnabledValue();
// set the callback functions value to hangle outgoing IPC message.
SendConfigMSG = ipcMSGCallBackFunc;
@ -111,6 +101,21 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
}
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredKeyboardManagerEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.KeyboardManager;
}
}
public bool Enabled
{
get
@ -277,6 +282,12 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
OnPropertyChanged(nameof(RemapShortcuts));
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(Enabled));
}
public bool LoadProfile()
{
var success = true;

View File

@ -36,6 +36,20 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
GeneralSettingsConfig = settingsRepository.SettingsConfig;
InitializeEnabledValue();
if (measureToolSettingsRepository == null)
{
throw new ArgumentNullException(nameof(measureToolSettingsRepository));
}
Settings = measureToolSettingsRepository.SettingsConfig;
SendConfigMSG = ipcMSGCallBackFunc;
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredScreenRulerEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
@ -47,15 +61,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
_isEnabled = GeneralSettingsConfig.Enabled.MeasureTool;
}
if (measureToolSettingsRepository == null)
{
throw new ArgumentNullException(nameof(measureToolSettingsRepository));
}
Settings = measureToolSettingsRepository.SettingsConfig;
SendConfigMSG = ipcMSGCallBackFunc;
}
public bool IsEnabled
@ -230,6 +235,13 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
SettingsUtils.SaveSettings(Settings.ToJsonString(), MeasureToolSettings.ModuleName);
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsEnabled));
OnPropertyChanged(nameof(ShowContinuousCaptureWarning));
}
public bool ShowContinuousCaptureWarning
{
get => IsEnabled && ContinuousCapture;

View File

@ -35,41 +35,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
GeneralSettingsConfig = settingsRepository.SettingsConfig;
_findMyMouseEnabledGpoRuleConfiguration = GPOWrapper.GetConfiguredFindMyMouseEnabledValue();
if (_findMyMouseEnabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _findMyMouseEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_findMyMouseEnabledStateIsGPOConfigured = true;
_isFindMyMouseEnabled = _findMyMouseEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isFindMyMouseEnabled = GeneralSettingsConfig.Enabled.FindMyMouse;
}
_highlighterEnabledGpoRuleConfiguration = GPOWrapper.GetConfiguredMouseHighlighterEnabledValue();
if (_highlighterEnabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _highlighterEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_highlighterEnabledStateIsGPOConfigured = true;
_isMouseHighlighterEnabled = _highlighterEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isMouseHighlighterEnabled = GeneralSettingsConfig.Enabled.MouseHighlighter;
}
_mousePointerCrosshairsEnabledGpoRuleConfiguration = GPOWrapper.GetConfiguredMousePointerCrosshairsEnabledValue();
if (_mousePointerCrosshairsEnabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _mousePointerCrosshairsEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_mousePointerCrosshairsEnabledStateIsGPOConfigured = true;
_isMousePointerCrosshairsEnabled = _mousePointerCrosshairsEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isMousePointerCrosshairsEnabled = GeneralSettingsConfig.Enabled.MousePointerCrosshairs;
}
InitializeEnabledValues();
// To obtain the find my mouse settings, if the file exists.
// If not, to create a file with the default settings and to return the default configurations.
@ -134,6 +100,45 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
SendConfigMSG = ipcMSGCallBackFunc;
}
private void InitializeEnabledValues()
{
_findMyMouseEnabledGpoRuleConfiguration = GPOWrapper.GetConfiguredFindMyMouseEnabledValue();
if (_findMyMouseEnabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _findMyMouseEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_findMyMouseEnabledStateIsGPOConfigured = true;
_isFindMyMouseEnabled = _findMyMouseEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isFindMyMouseEnabled = GeneralSettingsConfig.Enabled.FindMyMouse;
}
_highlighterEnabledGpoRuleConfiguration = GPOWrapper.GetConfiguredMouseHighlighterEnabledValue();
if (_highlighterEnabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _highlighterEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_highlighterEnabledStateIsGPOConfigured = true;
_isMouseHighlighterEnabled = _highlighterEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isMouseHighlighterEnabled = GeneralSettingsConfig.Enabled.MouseHighlighter;
}
_mousePointerCrosshairsEnabledGpoRuleConfiguration = GPOWrapper.GetConfiguredMousePointerCrosshairsEnabledValue();
if (_mousePointerCrosshairsEnabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _mousePointerCrosshairsEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_mousePointerCrosshairsEnabledStateIsGPOConfigured = true;
_isMousePointerCrosshairsEnabled = _mousePointerCrosshairsEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isMousePointerCrosshairsEnabled = GeneralSettingsConfig.Enabled.MousePointerCrosshairs;
}
}
public bool IsFindMyMouseEnabled
{
get => _isFindMyMouseEnabled;
@ -693,6 +698,14 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
SettingsUtils.SaveSettings(MousePointerCrosshairsSettingsConfig.ToJsonString(), MousePointerCrosshairsSettings.ModuleName);
}
public void RefreshEnabledState()
{
InitializeEnabledValues();
OnPropertyChanged(nameof(IsFindMyMouseEnabled));
OnPropertyChanged(nameof(IsMouseHighlighterEnabled));
OnPropertyChanged(nameof(IsMousePointerCrosshairsEnabled));
}
private Func<string, int> SendConfigMSG { get; }
private GpoRuleConfigured _findMyMouseEnabledGpoRuleConfiguration;

View File

@ -80,17 +80,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
_settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils));
GeneralSettingsConfig = settingsRepository.SettingsConfig;
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredQuickAccentEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.PowerAccent;
}
InitializeEnabledValue();
if (_settingsUtils.SettingsExists(PowerAccentSettings.ModuleName))
{
@ -113,6 +103,21 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
SendConfigMSG = ipcMSGCallBackFunc;
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredQuickAccentEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.PowerAccent;
}
}
public bool IsEnabled
{
get => _isEnabled;
@ -308,6 +313,12 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
}
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsEnabled));
}
private GpoRuleConfigured _enabledGpoRuleConfiguration;
private bool _enabledStateIsGPOConfigured;
private bool _isEnabled;

View File

@ -63,17 +63,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
GeneralSettingsConfig = settingsRepository.SettingsConfig;
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredPowerLauncherEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.PowerLauncher;
}
InitializeEnabledValue();
// set the callback functions value to hangle outgoing IPC message.
SendConfigMSG = ipcMSGCallBackFunc;
@ -118,6 +108,21 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
SearchPluginsCommand = new RelayCommand(SearchPlugins);
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredPowerLauncherEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.PowerLauncher;
}
}
private void OnPluginInfoChange(object sender, PropertyChangedEventArgs e)
{
if (
@ -175,6 +180,14 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
}
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(EnablePowerLauncher));
OnPropertyChanged(nameof(ShowAllPluginsDisabledWarning));
OnPropertyChanged(nameof(ShowPluginsLoadingMessage));
}
public bool IsEnabledGpoConfigured
{
get => _enabledStateIsGPOConfigured;

View File

@ -95,6 +95,19 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
_powerOcrSettings = powerOcrsettingsRepository.SettingsConfig;
InitializeEnabledValue();
// 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;
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredTextExtractorEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
@ -106,14 +119,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
_isEnabled = GeneralSettingsConfig.Enabled.PowerOCR;
}
// 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;
}
public bool IsEnabled
@ -237,6 +242,12 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
JsonSerializer.Serialize(_powerOcrSettings)));
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsEnabled));
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)

View File

@ -69,6 +69,11 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
_autoComplete = Settings.Properties.MRUEnabled.Value;
_powerRenameUseBoostLib = Settings.Properties.UseBoostLib.Value;
InitializeEnabledValue();
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredPowerRenameEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
@ -260,5 +265,12 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
SendConfigMSG(ipcMessage.ToJsonString());
}
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsEnabled));
OnPropertyChanged(nameof(GlobalAndMruEnabled));
}
}
}

View File

@ -5,10 +5,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Services;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;

View File

@ -53,17 +53,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
// set the callback functions value to hangle outgoing IPC message.
SendConfigMSG = ipcMSGCallBackFunc;
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredShortcutGuideEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.ShortcutGuide;
}
InitializeEnabledValue();
_useLegacyPressWinKeyBehavior = Settings.Properties.UseLegacyPressWinKeyBehavior.Value;
_pressTimeForGlobalWindowsShortcuts = Settings.Properties.PressTimeForGlobalWindowsShortcuts.Value;
@ -79,6 +69,21 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
}
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredShortcutGuideEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.ShortcutGuide;
}
}
private GpoRuleConfigured _enabledGpoRuleConfiguration;
private bool _enabledStateIsGPOConfigured;
private bool _isEnabled;
@ -267,5 +272,11 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
SendConfigMSG(ipcMessage.ToJsonString());
SettingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsEnabled));
}
}
}

View File

@ -92,17 +92,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
_selectedMicrophoneIndex = MicrophoneNames.FindIndex(name => name == Settings.Properties.SelectedMicrophone.Value);
}
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredVideoConferenceMuteEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.VideoConference;
}
InitializeEnabledValue();
_cameraAndMicrophoneMuteHotkey = Settings.Properties.MuteCameraAndMicrophoneHotkey.Value;
_microphoneMuteHotkey = Settings.Properties.MuteMicrophoneHotkey.Value;
@ -163,6 +153,21 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
}
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredVideoConferenceMuteEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.VideoConference;
}
}
private GpoRuleConfigured _enabledGpoRuleConfiguration;
private bool _enabledStateIsGPOConfigured;
private bool _isEnabled;
@ -473,6 +478,12 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
ModuleName,
JsonSerializer.Serialize(Settings)));
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsEnabled));
}
}
[ComImport]

View File

@ -2,13 +2,14 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class AlwaysOnTopPage : Page
public sealed partial class AlwaysOnTopPage : Page, IRefreshablePage
{
private AlwaysOnTopViewModel ViewModel { get; set; }
@ -19,5 +20,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
DataContext = ViewModel;
InitializeComponent();
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
}
}

View File

@ -2,13 +2,14 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class AwakePage : Page
public sealed partial class AwakePage : Page, IRefreshablePage
{
private AwakeViewModel ViewModel { get; set; }
@ -19,5 +20,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
DataContext = ViewModel;
InitializeComponent();
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
}
}

View File

@ -14,7 +14,7 @@ using Windows.ApplicationModel.Resources;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class ColorPickerPage : Page
public sealed partial class ColorPickerPage : Page, IRefreshablePage
{
public ColorPickerViewModel ViewModel { get; set; }
@ -157,5 +157,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{
ColorFormatDialog.IsPrimaryButtonEnabled = ViewModel.SetValidity(ColorFormatDialog.DataContext as ColorFormatModel, ColorFormatDialog.Tag as string);
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
}
}

View File

@ -2,13 +2,14 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class FancyZonesPage : Page
public sealed partial class FancyZonesPage : Page, IRefreshablePage
{
private FancyZonesViewModel ViewModel { get; set; }
@ -24,5 +25,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{
Helpers.StartProcessHelper.Start(Helpers.StartProcessHelper.ColorsSettings);
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
}
}

View File

@ -2,13 +2,14 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class FileLocksmithPage : Page
public sealed partial class FileLocksmithPage : Page, IRefreshablePage
{
private FileLocksmithViewModel ViewModel { get; set; }
@ -19,5 +20,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
DataContext = ViewModel;
InitializeComponent();
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
}
}

View File

@ -9,18 +9,14 @@
xmlns:ui="using:CommunityToolkit.WinUI.UI"
mc:Ignorable="d">
<controls:SettingsPageControl
x:Uid="Hosts"
ModuleImageSource="ms-appx:///Assets/Modules/AlwaysOnTop.png">
<controls:SettingsPageControl x:Uid="Hosts" ModuleImageSource="ms-appx:///Assets/Modules/AlwaysOnTop.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel Orientation="Vertical" ChildrenTransitions="{StaticResource SettingsCardsAnimations}">
<labs:SettingsCard
x:Uid="Hosts_EnableToggleControl_HeaderText"
HeaderIcon="{ui:BitmapIcon Source=/Assets/FluentIcons/FluentIconsHosts.png}"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured, Converter={StaticResource BoolNegationConverter}}">
<ToggleSwitch
x:Uid="ToggleSwitch"
IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" />
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" />
</labs:SettingsCard>
<InfoBar
x:Uid="GPO_IsSettingForced"
@ -28,9 +24,7 @@
IsOpen="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured}"
IsTabStop="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured}"
Severity="Informational" />
<controls:SettingsGroup
x:Uid="Hosts_Activation_GroupSettings"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<controls:SettingsGroup x:Uid="Hosts_Activation_GroupSettings" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<labs:SettingsCard
x:Uid="Hosts_LaunchButtonControl"
ActionIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily},
@ -45,30 +39,16 @@
HeaderIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily},
Glyph=&#xE7EF;}"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.LaunchAdministratorEnabled}">
<ToggleSwitch
x:Uid="ToggleSwitch"
IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.LaunchAdministrator}" />
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.LaunchAdministrator}" />
</labs:SettingsCard>
<labs:SettingsCard
x:Uid="Hosts_Toggle_ShowStartupWarning"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily},
Glyph=&#xE7BA;}">
<ToggleSwitch
x:Uid="ToggleSwitch"
IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.ShowStartupWarning}" />
<labs:SettingsCard x:Uid="Hosts_Toggle_ShowStartupWarning" HeaderIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily}, Glyph=&#xE7BA;}">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.ShowStartupWarning}" />
</labs:SettingsCard>
</controls:SettingsGroup>
<controls:SettingsGroup
x:Uid="Hosts_File_GroupSettings"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<labs:SettingsCard
x:Uid="Hosts_AdditionalLinesPosition"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily},
Glyph=&#xE8A5;}">
<ComboBox
MinWidth="{StaticResource SettingActionControlMinWidth}"
SelectedIndex="{x:Bind Path=ViewModel.AdditionalLinesPosition, Mode=TwoWay}">
<controls:SettingsGroup x:Uid="Hosts_File_GroupSettings" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<labs:SettingsCard x:Uid="Hosts_AdditionalLinesPosition" HeaderIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily}, Glyph=&#xE8A5;}">
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}" SelectedIndex="{x:Bind Path=ViewModel.AdditionalLinesPosition, Mode=TwoWay}">
<ComboBoxItem x:Uid="Hosts_AdditionalLinesPosition_Top" />
<ComboBoxItem x:Uid="Hosts_AdditionalLinesPosition_Bottom" />
</ComboBox>
@ -78,9 +58,7 @@
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink
x:Uid="LearnMore_Hosts"
Link="https://aka.ms/PowerToysOverview_HostsFileEditor" />
<controls:PageLink x:Uid="LearnMore_Hosts" Link="https://aka.ms/PowerToysOverview_HostsFileEditor" />
</controls:SettingsPageControl.PrimaryLinks>
</controls:SettingsPageControl>
</Page>

View File

@ -2,13 +2,14 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class HostsPage : Page
public sealed partial class HostsPage : Page, IRefreshablePage
{
private HostsViewModel ViewModel { get; }
@ -18,5 +19,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
var settingsUtils = new SettingsUtils();
ViewModel = new HostsViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), SettingsRepository<HostsSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, App.IsElevated);
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
}
}

View File

@ -21,18 +21,14 @@
FalseValue="1"
TrueValue="0" />
</Page.Resources>
<controls:SettingsPageControl
x:Uid="ImageResizer"
ModuleImageSource="ms-appx:///Assets/Modules/ImageResizer.png">
<controls:SettingsPageControl x:Uid="ImageResizer" ModuleImageSource="ms-appx:///Assets/Modules/ImageResizer.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel ChildrenTransitions="{StaticResource SettingsCardsAnimations}">
<labs:SettingsCard
x:Uid="ImageResizer_EnableToggle"
HeaderIcon="{ui:BitmapIcon Source=/Assets/FluentIcons/FluentIconsImageResizer.png}"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured, Converter={StaticResource BoolNegationConverter}}">
<ToggleSwitch
x:Uid="ToggleSwitch"
IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" />
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" />
</labs:SettingsCard>
<InfoBar
@ -42,13 +38,8 @@
IsTabStop="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured}"
Severity="Informational" />
<controls:SettingsGroup
x:Uid="ImageResizer_CustomSizes"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<labs:SettingsCard
x:Uid="ImageResizer_Presets"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily},
Glyph=&#xE792;}">
<controls:SettingsGroup x:Uid="ImageResizer_CustomSizes" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<labs:SettingsCard x:Uid="ImageResizer_Presets" HeaderIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily}, Glyph=&#xE792;}">
<Button
x:Uid="ImageResizer_AddSizeButton"
Click="AddSizeButton_Click"
@ -61,9 +52,7 @@
ItemsSource="{x:Bind ViewModel.Sizes, Mode=TwoWay}"
SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate
x:Name="SingleLineDataTemplate"
x:DataType="models:ImageSize">
<DataTemplate x:Name="SingleLineDataTemplate" x:DataType="models:ImageSize">
<labs:SettingsCard Header="{x:Bind Name, Mode=OneWay}">
<labs:SettingsCard.Resources>
<x:Double x:Key="SettingsCardLeftIndention">42</x:Double>
@ -122,9 +111,7 @@
</ToolTipService.ToolTip>
<Button.Flyout>
<Flyout x:Uid="ImageResizer_EditSize">
<StackPanel
Margin="0,12,0,0"
Spacing="16">
<StackPanel Margin="0,12,0,0" Spacing="16">
<TextBox
x:Uid="ImageResizer_Name"
Width="240"
@ -141,9 +128,7 @@
<ComboBoxItem x:Uid="ImageResizer_Sizes_Fit_Stretch" />
</ComboBox>
<StackPanel
Orientation="Horizontal"
Spacing="8">
<StackPanel Orientation="Horizontal" Spacing="8">
<NumberBox
x:Uid="ImageResizer_Width"
Width="116"
@ -196,13 +181,9 @@
</ListView>
</controls:SettingsGroup>
<controls:SettingsGroup
x:Uid="Encoding"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<controls:SettingsGroup x:Uid="Encoding" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<labs:SettingsCard x:Uid="ImageResizer_FallBackEncoderText">
<ComboBox
MinWidth="{StaticResource SettingActionControlMinWidth}"
SelectedIndex="{x:Bind Path=ViewModel.Encoder, Mode=TwoWay}">
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}" SelectedIndex="{x:Bind Path=ViewModel.Encoder, Mode=TwoWay}">
<ComboBoxItem x:Uid="ImageResizer_FallbackEncoder_PNG" />
<ComboBoxItem x:Uid="ImageResizer_FallbackEncoder_BMP" />
<ComboBoxItem x:Uid="ImageResizer_FallbackEncoder_JPEG" />
@ -221,9 +202,7 @@
</labs:SettingsCard>
<labs:SettingsCard x:Uid="ImageResizer_PNGInterlacing">
<ComboBox
MinWidth="{StaticResource SettingActionControlMinWidth}"
SelectedIndex="{x:Bind Mode=TwoWay, Path=ViewModel.PngInterlaceOption}">
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}" SelectedIndex="{x:Bind Mode=TwoWay, Path=ViewModel.PngInterlaceOption}">
<ComboBoxItem x:Uid="Default" />
<ComboBoxItem x:Uid="On" />
<ComboBoxItem x:Uid="Off" />
@ -231,9 +210,7 @@
</labs:SettingsCard>
<labs:SettingsCard x:Uid="ImageResizer_TIFFCompression">
<ComboBox
MinWidth="{StaticResource SettingActionControlMinWidth}"
SelectedIndex="{x:Bind Mode=TwoWay, Path=ViewModel.TiffCompressOption}">
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}" SelectedIndex="{x:Bind Mode=TwoWay, Path=ViewModel.TiffCompressOption}">
<ComboBoxItem x:Uid="ImageResizer_ENCODER_TIFF_Default" />
<ComboBoxItem x:Uid="ImageResizer_ENCODER_TIFF_None" />
<ComboBoxItem x:Uid="ImageResizer_ENCODER_TIFF_CCITT3" />
@ -245,13 +222,9 @@
</labs:SettingsCard>
</controls:SettingsGroup>
<controls:SettingsGroup
x:Uid="File"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<controls:SettingsGroup x:Uid="File" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<labs:SettingsCard x:Uid="ImageResizer_FilenameFormatHeader">
<StackPanel
Orientation="Horizontal"
Spacing="4">
<StackPanel Orientation="Horizontal" Spacing="4">
<TextBox
x:Uid="ImageResizer_FilenameFormatPlaceholder"
MinWidth="{StaticResource SettingActionControlMinWidth}"
@ -298,9 +271,7 @@
</labs:SettingsCard>
<labs:SettingsCard x:Uid="ImageResizer_FileModifiedDate">
<ComboBox
MinWidth="{StaticResource SettingActionControlMinWidth}"
SelectedIndex="{x:Bind Mode=TwoWay, Path=ViewModel.KeepDateModified, Converter={StaticResource ReverseBoolToComboBoxIndexConverter}}">
<ComboBox MinWidth="{StaticResource SettingActionControlMinWidth}" SelectedIndex="{x:Bind Mode=TwoWay, Path=ViewModel.KeepDateModified, Converter={StaticResource ReverseBoolToComboBoxIndexConverter}}">
<ComboBoxItem x:Uid="ImageResizer_UseOriginalDate" />
<ComboBoxItem x:Uid="ImageResizer_UseResizeDate" />
</ComboBox>
@ -311,14 +282,10 @@
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink
x:Uid="LearnMore_ImageResizer"
Link="https://aka.ms/PowerToysOverview_ImageResizer" />
<controls:PageLink x:Uid="LearnMore_ImageResizer" Link="https://aka.ms/PowerToysOverview_ImageResizer" />
</controls:SettingsPageControl.PrimaryLinks>
<controls:SettingsPageControl.SecondaryLinks>
<controls:PageLink
Link="https://github.com/bricelam/ImageResizer/"
Text="Brice Lambson's ImageResizer" />
<controls:PageLink Link="https://github.com/bricelam/ImageResizer/" Text="Brice Lambson's ImageResizer" />
</controls:SettingsPageControl.SecondaryLinks>
</controls:SettingsPageControl>
</Page>

View File

@ -4,6 +4,7 @@
using System;
using System.Globalization;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.ViewModels;
@ -13,7 +14,7 @@ using Windows.ApplicationModel.Resources;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class ImageResizerPage : Page
public sealed partial class ImageResizerPage : Page, IRefreshablePage
{
public ImageResizerViewModel ViewModel { get; set; }
@ -88,5 +89,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
ViewModel.IsListViewFocusRequested = false;
}
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
}
}

View File

@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.IO.Abstractions;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.ViewModels;
@ -16,7 +17,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class KeyboardManagerPage : Page
public sealed partial class KeyboardManagerPage : Page, IRefreshablePage
{
private const string PowerToyName = "Keyboard Manager";
@ -84,5 +85,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
return 0;
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
}
}

View File

@ -2,13 +2,14 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class MeasureToolPage : Page
public sealed partial class MeasureToolPage : Page, IRefreshablePage
{
private MeasureToolViewModel ViewModel { get; set; }
@ -26,5 +27,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
DataContext = ViewModel;
InitializeComponent();
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
}
}

View File

@ -2,13 +2,14 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class MouseUtilsPage : Page
public sealed partial class MouseUtilsPage : Page, IRefreshablePage
{
private MouseUtilsViewModel ViewModel { get; set; }
@ -42,5 +43,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
DataContext = ViewModel;
InitializeComponent();
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
}
}

View File

@ -2,13 +2,14 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class PowerAccentPage : Page
public sealed partial class PowerAccentPage : Page, IRefreshablePage
{
private PowerAccentViewModel ViewModel { get; set; }
@ -19,5 +20,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
DataContext = ViewModel;
this.InitializeComponent();
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
}
}

View File

@ -5,6 +5,7 @@
using System;
using System.Collections.ObjectModel;
using System.IO;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
@ -14,7 +15,7 @@ using Windows.ApplicationModel.Resources;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class PowerLauncherPage : Page
public sealed partial class PowerLauncherPage : Page, IRefreshablePage
{
public PowerLauncherViewModel ViewModel { get; set; }
@ -85,6 +86,11 @@ namespace Microsoft.PowerToys.Settings.UI.Views
Helpers.StartProcessHelper.Start(Helpers.StartProcessHelper.ColorsSettings);
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
/*
public Tuple<string, string> SelectedSearchResultPreference
{

View File

@ -2,13 +2,14 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class PowerOcrPage : Page
public sealed partial class PowerOcrPage : Page, IRefreshablePage
{
private PowerOcrViewModel ViewModel { get; set; }
@ -39,5 +40,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{
ViewModel.UpdateLanguages();
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
}
}

View File

@ -2,13 +2,14 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class PowerRenamePage : Page
public sealed partial class PowerRenamePage : Page, IRefreshablePage
{
private PowerRenameViewModel ViewModel { get; set; }
@ -20,5 +21,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
DataContext = ViewModel;
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
}
}

View File

@ -27,11 +27,31 @@ namespace Microsoft.PowerToys.Settings.UI.Views
/// <param name="msg">message.</param>
public delegate void IPCMessageCallback(string msg);
/// <summary>
/// Declaration for the opening main window callback function.
/// </summary>
public delegate void MainOpeningCallback();
/// <summary>
/// Declaration for the updating the general settings callback function.
/// </summary>
public delegate bool UpdatingGeneralSettingsCallback(string module, bool isEnabled);
/// <summary>
/// Declaration for the opening oobe window callback function.
/// </summary>
public delegate void OobeOpeningCallback();
/// <summary>
/// Declaration for the opening flyout window callback function.
/// </summary>
public delegate void FlyoutOpeningCallback();
/// <summary>
/// Declaration for the disabling hide of flyout window callback function.
/// </summary>
public delegate void DisablingFlyoutHidingCallback();
/// <summary>
/// Gets or sets a shell handler to be used to update contents of the shell dynamically from page within the frame.
/// </summary>
@ -52,11 +72,31 @@ namespace Microsoft.PowerToys.Settings.UI.Views
/// </summary>
public static IPCMessageCallback CheckForUpdatesMsgCallback { get; set; }
/// <summary>
/// Gets or sets callback function for opening main window
/// </summary>
public static MainOpeningCallback OpenMainWindowCallback { get; set; }
/// <summary>
/// Gets or sets callback function for updating the general settings
/// </summary>
public static UpdatingGeneralSettingsCallback UpdateGeneralSettingsCallback { get; set; }
/// <summary>
/// Gets or sets callback function for opening oobe window
/// </summary>
public static OobeOpeningCallback OpenOobeWindowCallback { get; set; }
/// <summary>
/// Gets or sets callback function for opening flyout window
/// </summary>
public static FlyoutOpeningCallback OpenFlyoutCallback { get; set; }
/// <summary>
/// Gets or sets callback function for disabling hide of flyout window
/// </summary>
public static DisablingFlyoutHidingCallback DisableFlyoutHidingCallback { get; set; }
/// <summary>
/// Gets view model.
/// </summary>
@ -82,7 +122,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
DataContext = ViewModel;
ShellHandler = this;
ViewModel.Initialize(shellFrame, navigationView, KeyboardAccelerators);
shellFrame.Navigate(typeof(GeneralPage));
// NL moved navigation to general page to the moment when the window is first activated (to not make flyout window disappear)
// shellFrame.Navigate(typeof(GeneralPage));
IPCResponseHandleList.Add(ReceiveMessage);
}
public static int SendDefaultIPCMessage(string msg)
@ -131,6 +174,24 @@ namespace Microsoft.PowerToys.Settings.UI.Views
CheckForUpdatesMsgCallback = implementation;
}
/// <summary>
/// Set main window opening callback function
/// </summary>
/// <param name="implementation">delegate function implementation.</param>
public static void SetOpenMainWindowCallback(MainOpeningCallback implementation)
{
OpenMainWindowCallback = implementation;
}
/// <summary>
/// Set updating the general settings callback function
/// </summary>
/// <param name="implementation">delegate function implementation.</param>
public static void SetUpdatingGeneralSettingsCallback(UpdatingGeneralSettingsCallback implementation)
{
UpdateGeneralSettingsCallback = implementation;
}
/// <summary>
/// Set oobe opening callback function
/// </summary>
@ -140,6 +201,24 @@ namespace Microsoft.PowerToys.Settings.UI.Views
OpenOobeWindowCallback = implementation;
}
/// <summary>
/// Set flyout opening callback function
/// </summary>
/// <param name="implementation">delegate function implementation.</param>
public static void SetOpenFlyoutCallback(FlyoutOpeningCallback implementation)
{
OpenFlyoutCallback = implementation;
}
/// <summary>
/// Set disable flyout hiding callback function
/// </summary>
/// <param name="implementation">delegate function implementation.</param>
public static void SetDisableFlyoutHidingCallback(DisablingFlyoutHidingCallback implementation)
{
DisableFlyoutHidingCallback = implementation;
}
public static void SetElevationStatus(bool isElevated)
{
IsElevated = isElevated;
@ -160,6 +239,16 @@ namespace Microsoft.PowerToys.Settings.UI.Views
shellFrame.Navigate(typeof(GeneralPage));
}
// Tell the current page view model to update
public void SignalGeneralDataUpdate()
{
IRefreshablePage currentPage = shellFrame?.Content as IRefreshablePage;
if (currentPage != null)
{
currentPage.RefreshEnabledState();
}
}
private void OobeButton_Click(object sender, RoutedEventArgs e)
{
OpenOobeWindowCallback();
@ -236,5 +325,28 @@ namespace Microsoft.PowerToys.Settings.UI.Views
NavigationService.Navigate(pageType);
}
}
private void ReceiveMessage(JsonObject json)
{
if (json != null)
{
if (json.ToString().StartsWith("{\"ShowYourself\":"))
{
if (json.ToString().EndsWith("\"flyout\"}"))
{
OpenFlyoutCallback();
}
else if (json.ToString().EndsWith("\"main_page\"}"))
{
OpenMainWindowCallback();
}
}
}
}
internal static void EnsurePageIsSelected()
{
NavigationService.EnsurePageIsSelected(typeof(GeneralPage));
}
}
}

View File

@ -2,13 +2,14 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class ShortcutGuidePage : Page
public sealed partial class ShortcutGuidePage : Page, IRefreshablePage
{
private ShortcutGuideViewModel ViewModel { get; set; }
@ -25,5 +26,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{
Helpers.StartProcessHelper.Start(Helpers.StartProcessHelper.ColorsSettings);
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
}
}

View File

@ -4,6 +4,7 @@
using System;
using System.Threading.Tasks;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.UI.Xaml.Controls;
@ -12,7 +13,7 @@ using Windows.Storage.Pickers;
namespace Microsoft.PowerToys.Settings.UI.Views
{
public sealed partial class VideoConferencePage : Page
public sealed partial class VideoConferencePage : Page, IRefreshablePage
{
private VideoConferenceViewModel ViewModel { get; set; }
@ -43,5 +44,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
DataContext = ViewModel;
InitializeComponent();
}
public void RefreshEnabledState()
{
ViewModel.RefreshEnabledState();
}
}
}