mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-07 03:36:44 +02:00
[FancyZones Editor] New UX for the FZ editor. (#9325)
* Removed MetroWindow, added theming support and modernWPF * Rmoved MahApps refs * Removed MahApps * Updated canvas zones * Updated GridEditor * Fixes * UI updates * New layout type selection dialog * New editor UI * Updates * Fix * UI enhancements * Updated UI * Added styles to layoutpreview * Accesibility improvements * Accesibility and styling improvements * Fix * Cleaned up brushes * Updated UX * Updated UI * Added no layouts description * Fix * UI fixes * [FZ Editor] Serialize/deserialize settings (#8615) * conflicts fix * [FZ Editor] Parse json file instead of command line args (#8649) * [FZ Editor] Serialize/deserialize settings fix (#8707) * [FZ Editor] Hide unsupported settings in custom layouts flyouts (#8716) * [FZ Editor] Duplicate custom layouts (#8718) * [FZ Editor] Duplicate layout behavior (#8720) * New UX proposal * Updated spacing * Switching to toggleswitches * Revert toggleswitch * Updated colorbrush * Updated string for saving label * Updated UI * Dark theme color fixes * Removed space * [FZ Editor] Bind dialog properties (#9199) * Resize editor window to fit the content in single-monitor mode (#9203) * Editor opening fix (#9207) * Disable "Create" button if the Name textbox is empty (#9212) * [FZ Editor] Changed edit dialog for template layouts. (#9233) * [FZ Editor] Small fixes and refactoring. (#9236) * new layout creation refactoring * "Save and apply" applies the layout * number of zones header hide * [FZ Editor] Empty layout template. (#9237) * [FZ Editor] Move "Duplicate" and "Delete" buttons to the Edit dialog. (#9272) * [FZ Editor] Preview the applied layout after editing another layout. (#9278) * Fixed "Save and apply" button behavior (#9286) * [FZ Editor] Save template layouts in the settings. (#9283) * Added default custom layout name (#9291) * close dialog before opening zones editor (#9302) * Pressing Esc closes dialogs (#9301) * [FZ Editor] Reset applied layout to "No layout" if it was deleted. (#9315) * [FZ Editor] Dark theme colors (#9317) * "Number of zones" buttons colors. (#9321) * rebase fix * added ModernWpf.dll * address PR comments: updated colors * added comments, replaced magic numbers * refactoring * merge zones crash fix * removed redundant using directive Co-authored-by: Niels Laute <niels9001@hotmail.com> Co-authored-by: Niels Laute <niels.laute@live.nl>
This commit is contained in:
@@ -621,6 +621,12 @@ void FancyZones::ToggleEditor() noexcept
|
||||
return;
|
||||
}
|
||||
|
||||
wil::unique_cotaskmem_string virtualDesktopId;
|
||||
if (!SUCCEEDED(StringFromCLSID(m_currentDesktopId, &virtualDesktopId)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Divider: /
|
||||
* Parts:
|
||||
@@ -639,13 +645,16 @@ void FancyZones::ToggleEditor() noexcept
|
||||
std::wstring params;
|
||||
const std::wstring divider = L"/";
|
||||
params += std::to_wstring(GetCurrentProcessId()) + divider; /* Process id */
|
||||
|
||||
const bool spanZonesAcrossMonitors = m_settings->GetSettings()->spanZonesAcrossMonitors;
|
||||
params += std::to_wstring(spanZonesAcrossMonitors) + divider; /* Span zones */
|
||||
|
||||
std::vector<std::pair<HMONITOR, MONITORINFOEX>> allMonitors;
|
||||
allMonitors = FancyZonesUtils::GetAllMonitorInfo<&MONITORINFOEX::rcWork>();
|
||||
|
||||
if (spanZonesAcrossMonitors)
|
||||
{
|
||||
params += FancyZonesUtils::GenerateUniqueIdAllMonitorsArea(virtualDesktopId.get()) + divider; /* Monitor id where the Editor should be opened */
|
||||
}
|
||||
|
||||
// device id map
|
||||
std::unordered_map<std::wstring, DWORD> displayDeviceIdxMap;
|
||||
|
||||
@@ -657,25 +666,15 @@ void FancyZones::ToggleEditor() noexcept
|
||||
HMONITOR monitor = monitorData.first;
|
||||
auto monitorInfo = monitorData.second;
|
||||
|
||||
std::wstring monitorId;
|
||||
std::wstring deviceId = FancyZonesUtils::GetDisplayDeviceId(monitorInfo.szDevice, displayDeviceIdxMap);
|
||||
wil::unique_cotaskmem_string virtualDesktopId;
|
||||
if (SUCCEEDED(StringFromCLSID(m_currentDesktopId, &virtualDesktopId)))
|
||||
{
|
||||
monitorId = FancyZonesUtils::GenerateUniqueId(monitor, deviceId, virtualDesktopId.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
std::wstring monitorId = FancyZonesUtils::GenerateUniqueId(monitor, deviceId, virtualDesktopId.get());
|
||||
|
||||
if (monitor == targetMonitor)
|
||||
if (monitor == targetMonitor && !spanZonesAcrossMonitors)
|
||||
{
|
||||
params += monitorId + divider; /* Monitor id where the Editor should be opened */
|
||||
}
|
||||
|
||||
monitorsDataStr += std::move(monitorId) + divider; /* Monitor id */
|
||||
|
||||
UINT dpiX = 0;
|
||||
UINT dpiY = 0;
|
||||
if (GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY) == S_OK)
|
||||
@@ -690,13 +689,15 @@ void FancyZones::ToggleEditor() noexcept
|
||||
prevDpiY = dpiY;
|
||||
}
|
||||
|
||||
monitorsDataStr += std::to_wstring(monitorInfo.rcMonitor.left) + divider;
|
||||
monitorsDataStr += std::to_wstring(monitorInfo.rcMonitor.top) + divider;
|
||||
monitorsDataStr += std::to_wstring(monitorInfo.rcMonitor.left) + divider; /* Top coordinate */
|
||||
monitorsDataStr += std::to_wstring(monitorInfo.rcMonitor.top) + divider; /* Left coordinate */
|
||||
}
|
||||
|
||||
params += std::to_wstring(allMonitors.size()) + divider; /* Monitors count */
|
||||
params += monitorsDataStr;
|
||||
|
||||
FancyZonesDataInstance().SaveFancyZonesEditorParameters(spanZonesAcrossMonitors, virtualDesktopId.get(), targetMonitor); /* Write parameters to json file */
|
||||
|
||||
if (showDpiWarning)
|
||||
{
|
||||
// We must show the message box in a separate thread, since this code is called from a low-level
|
||||
@@ -709,9 +710,6 @@ void FancyZones::ToggleEditor() noexcept
|
||||
//} }.detach();
|
||||
}
|
||||
|
||||
const auto& fancyZonesData = FancyZonesDataInstance();
|
||||
fancyZonesData.SerializeDeviceInfoToTmpFile(m_currentDesktopId);
|
||||
|
||||
SHELLEXECUTEINFO sei{ sizeof(sei) };
|
||||
sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI };
|
||||
sei.lpFile = NonLocalizable::FZEditorExecutablePath;
|
||||
@@ -1304,7 +1302,7 @@ bool FancyZones::IsSplashScreen(HWND window)
|
||||
void FancyZones::OnEditorExitEvent() noexcept
|
||||
{
|
||||
// Collect information about changes in zone layout after editor exited.
|
||||
FancyZonesDataInstance().ParseDataFromTmpFiles();
|
||||
FancyZonesDataInstance().LoadFancyZonesData();
|
||||
UpdateZoneSets();
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "Settings.h"
|
||||
|
||||
#include <common/utils/json.h>
|
||||
#include <fancyzones/lib/util.h>
|
||||
|
||||
#include <shlwapi.h>
|
||||
#include <filesystem>
|
||||
@@ -24,12 +25,9 @@ namespace NonLocalizable
|
||||
|
||||
const wchar_t FancyZonesDataFile[] = L"zones-settings.json";
|
||||
const wchar_t FancyZonesAppZoneHistoryFile[] = L"app-zone-history.json";
|
||||
const wchar_t FancyZonesEditorParametersFile[] = L"editor-parameters.json";
|
||||
const wchar_t DefaultGuid[] = L"{00000000-0000-0000-0000-000000000000}";
|
||||
const wchar_t RegistryPath[] = L"Software\\SuperFancyZones";
|
||||
|
||||
const wchar_t ActiveZoneSetsTmpFileName[] = L"FancyZonesActiveZoneSets.json";
|
||||
const wchar_t AppliedZoneSetsTmpFileName[] = L"FancyZonesAppliedZoneSets.json";
|
||||
const wchar_t DeletedCustomZoneSetsTmpFileName[] = L"FancyZonesDeletedCustomZoneSets.json";
|
||||
}
|
||||
|
||||
namespace
|
||||
@@ -151,10 +149,7 @@ FancyZonesData::FancyZonesData()
|
||||
|
||||
zonesSettingsFileName = saveFolderPath + L"\\" + std::wstring(NonLocalizable::FancyZonesDataFile);
|
||||
appZoneHistoryFileName = saveFolderPath + L"\\" + std::wstring(NonLocalizable::FancyZonesAppZoneHistoryFile);
|
||||
|
||||
activeZoneSetTmpFileName = GetTempDirPath() + NonLocalizable::ActiveZoneSetsTmpFileName;
|
||||
appliedZoneSetTmpFileName = GetTempDirPath() + NonLocalizable::AppliedZoneSetsTmpFileName;
|
||||
deletedCustomZoneSetsTmpFileName = GetTempDirPath() + NonLocalizable::DeletedCustomZoneSetsTmpFileName;
|
||||
editorParametersFileName = saveFolderPath + L"\\" + std::wstring(NonLocalizable::FancyZonesEditorParametersFile);
|
||||
}
|
||||
|
||||
std::optional<FancyZonesDataTypes::DeviceInfoData> FancyZonesData::FindDeviceInfo(const std::wstring& zoneWindowId) const
|
||||
@@ -479,54 +474,6 @@ void FancyZonesData::SetActiveZoneSet(const std::wstring& deviceId, const FancyZ
|
||||
}
|
||||
}
|
||||
|
||||
void FancyZonesData::SerializeDeviceInfoToTmpFile(const GUID& currentVirtualDesktop) const
|
||||
{
|
||||
JSONHelpers::SerializeDeviceInfoToTmpFile(deviceInfoMap, currentVirtualDesktop, activeZoneSetTmpFileName);
|
||||
}
|
||||
|
||||
void FancyZonesData::ParseDataFromTmpFiles()
|
||||
{
|
||||
ParseDeviceInfoFromTmpFile(activeZoneSetTmpFileName);
|
||||
ParseDeletedCustomZoneSetsFromTmpFile(deletedCustomZoneSetsTmpFileName);
|
||||
ParseCustomZoneSetsFromTmpFile(appliedZoneSetTmpFileName);
|
||||
SaveFancyZonesData();
|
||||
}
|
||||
|
||||
void FancyZonesData::ParseDeviceInfoFromTmpFile(std::wstring_view tmpFilePath)
|
||||
{
|
||||
std::scoped_lock lock{ dataLock };
|
||||
const auto& appliedZonesets = JSONHelpers::ParseDeviceInfoFromTmpFile(tmpFilePath);
|
||||
|
||||
if (appliedZonesets)
|
||||
{
|
||||
for (const auto& zoneset : *appliedZonesets)
|
||||
{
|
||||
deviceInfoMap[zoneset.first] = std::move(zoneset.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FancyZonesData::ParseCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath)
|
||||
{
|
||||
std::scoped_lock lock{ dataLock };
|
||||
const auto& customZoneSets = JSONHelpers::ParseCustomZoneSetsFromTmpFile(tmpFilePath);
|
||||
|
||||
for (const auto& zoneSet : customZoneSets)
|
||||
{
|
||||
customZoneSetsMap[zoneSet.uuid] = zoneSet.data;
|
||||
}
|
||||
}
|
||||
|
||||
void FancyZonesData::ParseDeletedCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath)
|
||||
{
|
||||
std::scoped_lock lock{ dataLock };
|
||||
const auto& deletedCustomZoneSets = JSONHelpers::ParseDeletedCustomZoneSetsFromTmpFile(tmpFilePath);
|
||||
for (const auto& zoneSet : deletedCustomZoneSets)
|
||||
{
|
||||
customZoneSetsMap.erase(zoneSet);
|
||||
}
|
||||
}
|
||||
|
||||
json::JsonObject FancyZonesData::GetPersistFancyZonesJSON()
|
||||
{
|
||||
return JSONHelpers::GetPersistFancyZonesJSON(zonesSettingsFileName, appZoneHistoryFileName);
|
||||
@@ -569,6 +516,69 @@ void FancyZonesData::SaveAppZoneHistory() const
|
||||
JSONHelpers::SaveAppZoneHistory(appZoneHistoryFileName, appZoneHistoryMap);
|
||||
}
|
||||
|
||||
void FancyZonesData::SaveFancyZonesEditorParameters(bool spanZonesAcrossMonitors, const std::wstring& virtualDesktopId, const HMONITOR& targetMonitor) const
|
||||
{
|
||||
JSONHelpers::EditorArgs argsJson; /* json arguments */
|
||||
argsJson.processId = GetCurrentProcessId(); /* Process id */
|
||||
argsJson.spanZonesAcrossMonitors = spanZonesAcrossMonitors; /* Span zones */
|
||||
|
||||
if (spanZonesAcrossMonitors)
|
||||
{
|
||||
auto monitorRect = FancyZonesUtils::GetAllMonitorsCombinedRect<&MONITORINFOEX::rcWork>();
|
||||
std::wstring monitorId = FancyZonesUtils::GenerateUniqueIdAllMonitorsArea(virtualDesktopId);
|
||||
|
||||
JSONHelpers::MonitorInfo monitorJson;
|
||||
monitorJson.id = monitorId;
|
||||
monitorJson.top = monitorRect.top;
|
||||
monitorJson.left = monitorRect.left;
|
||||
monitorJson.isSelected = true;
|
||||
monitorJson.dpi = 0; // unused
|
||||
|
||||
argsJson.monitors.emplace_back(std::move(monitorJson)); /* add monitor data */
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<std::pair<HMONITOR, MONITORINFOEX>> allMonitors;
|
||||
allMonitors = FancyZonesUtils::GetAllMonitorInfo<&MONITORINFOEX::rcWork>();
|
||||
|
||||
// device id map for correct device ids
|
||||
std::unordered_map<std::wstring, DWORD> displayDeviceIdxMap;
|
||||
|
||||
for (auto& monitorData : allMonitors)
|
||||
{
|
||||
HMONITOR monitor = monitorData.first;
|
||||
auto monitorInfo = monitorData.second;
|
||||
|
||||
JSONHelpers::MonitorInfo monitorJson;
|
||||
|
||||
std::wstring deviceId = FancyZonesUtils::GetDisplayDeviceId(monitorInfo.szDevice, displayDeviceIdxMap);
|
||||
std::wstring monitorId = FancyZonesUtils::GenerateUniqueId(monitor, deviceId, virtualDesktopId);
|
||||
|
||||
if (monitor == targetMonitor)
|
||||
{
|
||||
monitorJson.isSelected = true; /* Is monitor selected for the main editor window opening */
|
||||
}
|
||||
|
||||
monitorJson.id = monitorId; /* Monitor id */
|
||||
|
||||
UINT dpiX = 0;
|
||||
UINT dpiY = 0;
|
||||
if (GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY) == S_OK)
|
||||
{
|
||||
monitorJson.dpi = dpiX; /* DPI */
|
||||
}
|
||||
|
||||
monitorJson.top = monitorInfo.rcMonitor.top; /* Top coordinate */
|
||||
monitorJson.left = monitorInfo.rcMonitor.left; /* Left coordinate */
|
||||
|
||||
argsJson.monitors.emplace_back(std::move(monitorJson)); /* add monitor data */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
json::to_file(editorParametersFileName, JSONHelpers::EditorArgs::ToJson(argsJson));
|
||||
}
|
||||
|
||||
void FancyZonesData::RemoveDesktopAppZoneHistory(const std::wstring& desktopId)
|
||||
{
|
||||
for (auto it = std::begin(appZoneHistoryMap); it != std::end(appZoneHistoryMap);)
|
||||
|
||||
@@ -78,9 +78,6 @@ public:
|
||||
|
||||
void SetActiveZoneSet(const std::wstring& deviceId, const FancyZonesDataTypes::ZoneSetData& zoneSet);
|
||||
|
||||
void SerializeDeviceInfoToTmpFile(const GUID& currentVirtualDesktop) const;
|
||||
void ParseDataFromTmpFiles();
|
||||
|
||||
json::JsonObject GetPersistFancyZonesJSON();
|
||||
|
||||
void LoadFancyZonesData();
|
||||
@@ -88,6 +85,8 @@ public:
|
||||
void SaveZoneSettings() const;
|
||||
void SaveAppZoneHistory() const;
|
||||
|
||||
void SaveFancyZonesEditorParameters(bool spanZonesAcrossMonitors, const std::wstring& virtualDesktopId, const HMONITOR& targetMonitor) const;
|
||||
|
||||
private:
|
||||
#if defined(UNIT_TESTS)
|
||||
friend class FancyZonesUnitTests::FancyZonesDataUnitTests;
|
||||
@@ -101,6 +100,11 @@ private:
|
||||
deviceInfoMap[deviceId] = data;
|
||||
}
|
||||
|
||||
inline void SetCustomZonesets(const std::wstring& uuid, FancyZonesDataTypes::CustomZoneSetData data)
|
||||
{
|
||||
customZoneSetsMap[uuid] = data;
|
||||
}
|
||||
|
||||
inline bool ParseDeviceInfos(const json::JsonObject& fancyZonesDataJSON)
|
||||
{
|
||||
deviceInfoMap = JSONHelpers::ParseDeviceInfos(fancyZonesDataJSON);
|
||||
@@ -121,10 +125,6 @@ private:
|
||||
appZoneHistoryFileName = result + L"\\" + std::wstring(L"app-zone-history.json");
|
||||
}
|
||||
#endif
|
||||
void ParseDeviceInfoFromTmpFile(std::wstring_view tmpFilePath);
|
||||
void ParseCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath);
|
||||
void ParseDeletedCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath);
|
||||
|
||||
void RemoveDesktopAppZoneHistory(const std::wstring& desktopId);
|
||||
|
||||
// Maps app path to app's zone history data
|
||||
@@ -136,10 +136,7 @@ private:
|
||||
|
||||
std::wstring zonesSettingsFileName;
|
||||
std::wstring appZoneHistoryFileName;
|
||||
|
||||
std::wstring activeZoneSetTmpFileName;
|
||||
std::wstring appliedZoneSetTmpFileName;
|
||||
std::wstring deletedCustomZoneSetsTmpFileName;
|
||||
std::wstring editorParametersFileName;
|
||||
|
||||
mutable std::recursive_mutex dataLock;
|
||||
};
|
||||
|
||||
@@ -45,6 +45,7 @@ namespace FancyZonesDataTypes
|
||||
int height;
|
||||
};
|
||||
std::vector<CanvasLayoutInfo::Rect> zones;
|
||||
int sensitivityRadius;
|
||||
};
|
||||
|
||||
struct GridLayoutInfo
|
||||
@@ -62,6 +63,9 @@ namespace FancyZonesDataTypes
|
||||
const std::vector<int>& rowsPercents;
|
||||
const std::vector<int>& columnsPercents;
|
||||
const std::vector<std::vector<int>>& cellChildMap;
|
||||
bool showSpacing;
|
||||
int spacing;
|
||||
int sensitivityRadius;
|
||||
};
|
||||
|
||||
GridLayoutInfo(const Minimal& info);
|
||||
@@ -74,16 +78,22 @@ namespace FancyZonesDataTypes
|
||||
|
||||
inline int rows() const { return m_rows; }
|
||||
inline int columns() const { return m_columns; }
|
||||
|
||||
inline const std::vector<int>& rowsPercents() const { return m_rowsPercents; };
|
||||
inline const std::vector<int>& columnsPercents() const { return m_columnsPercents; };
|
||||
inline const std::vector<std::vector<int>>& cellChildMap() const { return m_cellChildMap; };
|
||||
|
||||
inline bool showSpacing() const { return m_showSpacing; }
|
||||
inline int spacing() const { return m_spacing; }
|
||||
inline int sensitivityRadius() const { return m_sensitivityRadius; }
|
||||
|
||||
int m_rows;
|
||||
int m_columns;
|
||||
std::vector<int> m_rowsPercents;
|
||||
std::vector<int> m_columnsPercents;
|
||||
std::vector<std::vector<int>> m_cellChildMap;
|
||||
bool m_showSpacing;
|
||||
int m_spacing;
|
||||
int m_sensitivityRadius;
|
||||
};
|
||||
|
||||
struct CustomZoneSetData
|
||||
|
||||
@@ -17,16 +17,13 @@
|
||||
namespace NonLocalizable
|
||||
{
|
||||
const wchar_t ActiveZoneSetStr[] = L"active-zoneset";
|
||||
const wchar_t AppliedZonesets[] = L"applied-zonesets";
|
||||
const wchar_t AppPathStr[] = L"app-path";
|
||||
const wchar_t AppZoneHistoryStr[] = L"app-zone-history";
|
||||
const wchar_t CanvasStr[] = L"canvas";
|
||||
const wchar_t CellChildMapStr[] = L"cell-child-map";
|
||||
const wchar_t ColumnsPercentageStr[] = L"columns-percentage";
|
||||
const wchar_t ColumnsStr[] = L"columns";
|
||||
const wchar_t CreatedCustomZoneSets[] = L"created-custom-zone-sets";
|
||||
const wchar_t CustomZoneSetsStr[] = L"custom-zone-sets";
|
||||
const wchar_t DeletedCustomZoneSetsStr[] = L"deleted-custom-zone-sets";
|
||||
const wchar_t DeviceIdStr[] = L"device-id";
|
||||
const wchar_t DevicesStr[] = L"devices";
|
||||
const wchar_t EditorShowSpacingStr[] = L"editor-show-spacing";
|
||||
@@ -42,6 +39,10 @@ namespace NonLocalizable
|
||||
const wchar_t RefWidthStr[] = L"ref-width";
|
||||
const wchar_t RowsPercentageStr[] = L"rows-percentage";
|
||||
const wchar_t RowsStr[] = L"rows";
|
||||
const wchar_t SensitivityRadius[] = L"sensitivity-radius";
|
||||
const wchar_t ShowSpacing[] = L"show-spacing";
|
||||
const wchar_t Spacing[] = L"spacing";
|
||||
const wchar_t Templates[] = L"templates";
|
||||
const wchar_t TypeStr[] = L"type";
|
||||
const wchar_t UuidStr[] = L"uuid";
|
||||
const wchar_t WidthStr[] = L"width";
|
||||
@@ -51,6 +52,16 @@ namespace NonLocalizable
|
||||
const wchar_t ZoneIndexStr[] = L"zone-index";
|
||||
const wchar_t ZoneSetUuidStr[] = L"zoneset-uuid";
|
||||
const wchar_t ZonesStr[] = L"zones";
|
||||
|
||||
// Editor arguments
|
||||
const wchar_t Dpi[] = L"dpi";
|
||||
const wchar_t MonitorId[] = L"monitor-id";
|
||||
const wchar_t TopCoordinate[] = L"top-coordinate";
|
||||
const wchar_t LeftCoordinate[] = L"left-coordinate";
|
||||
const wchar_t IsSelected[] = L"is-selected";
|
||||
const wchar_t ProcessId[] = L"process-id";
|
||||
const wchar_t SpanZonesAcrossMonitors[] = L"span-zones-across-monitors";
|
||||
const wchar_t Monitors[] = L"monitors";
|
||||
}
|
||||
|
||||
namespace
|
||||
@@ -130,6 +141,7 @@ namespace JSONHelpers
|
||||
zonesJson.Append(zoneJson);
|
||||
}
|
||||
infoJson.SetNamedValue(NonLocalizable::ZonesStr, zonesJson);
|
||||
infoJson.SetNamedValue(NonLocalizable::SensitivityRadius, json::value(canvasInfo.sensitivityRadius));
|
||||
return infoJson;
|
||||
}
|
||||
|
||||
@@ -154,6 +166,8 @@ namespace JSONHelpers
|
||||
FancyZonesDataTypes::CanvasLayoutInfo::Rect zone{ x, y, width, height };
|
||||
info.zones.push_back(zone);
|
||||
}
|
||||
|
||||
info.sensitivityRadius = static_cast<int>(infoJson.GetNamedNumber(NonLocalizable::SensitivityRadius, DefaultValues::SensitivityRadius));
|
||||
return info;
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
@@ -176,6 +190,10 @@ namespace JSONHelpers
|
||||
cellChildMapJson.Append(NumVecToJsonArray(gridInfo.m_cellChildMap[i]));
|
||||
}
|
||||
infoJson.SetNamedValue(NonLocalizable::CellChildMapStr, cellChildMapJson);
|
||||
|
||||
infoJson.SetNamedValue(NonLocalizable::SensitivityRadius, json::value(gridInfo.m_sensitivityRadius));
|
||||
infoJson.SetNamedValue(NonLocalizable::ShowSpacing, json::value(gridInfo.m_showSpacing));
|
||||
infoJson.SetNamedValue(NonLocalizable::Spacing, json::value(gridInfo.m_spacing));
|
||||
|
||||
return infoJson;
|
||||
}
|
||||
@@ -210,6 +228,10 @@ namespace JSONHelpers
|
||||
info.cellChildMap().push_back(JsonArrayToNumVec(cellsArray));
|
||||
}
|
||||
|
||||
info.m_showSpacing = infoJson.GetNamedBoolean(NonLocalizable::ShowSpacing, DefaultValues::ShowSpacing);
|
||||
info.m_spacing = static_cast<int>(infoJson.GetNamedNumber(NonLocalizable::Spacing, DefaultValues::Spacing));
|
||||
info.m_sensitivityRadius = static_cast<int>(infoJson.GetNamedNumber(NonLocalizable::SensitivityRadius, DefaultValues::SensitivityRadius));
|
||||
|
||||
return info;
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
@@ -449,64 +471,37 @@ namespace JSONHelpers
|
||||
}
|
||||
}
|
||||
|
||||
json::JsonObject AppliedZonesetsJSON::ToJson(const TDeviceInfoMap& deviceInfoMap)
|
||||
json::JsonObject MonitorInfo::ToJson(const MonitorInfo& monitor)
|
||||
{
|
||||
json::JsonObject result{};
|
||||
|
||||
json::JsonArray array;
|
||||
for (const auto& info : deviceInfoMap)
|
||||
{
|
||||
JSONHelpers::DeviceInfoJSON deviceInfoJson{ info.first, info.second };
|
||||
array.Append(JSONHelpers::DeviceInfoJSON::ToJson(deviceInfoJson));
|
||||
}
|
||||
result.SetNamedValue(NonLocalizable::Dpi, json::value(monitor.dpi));
|
||||
result.SetNamedValue(NonLocalizable::MonitorId, json::value(monitor.id));
|
||||
result.SetNamedValue(NonLocalizable::TopCoordinate, json::value(monitor.top));
|
||||
result.SetNamedValue(NonLocalizable::LeftCoordinate, json::value(monitor.left));
|
||||
result.SetNamedValue(NonLocalizable::IsSelected, json::value(monitor.isSelected));
|
||||
|
||||
result.SetNamedValue(NonLocalizable::AppliedZonesets, array);
|
||||
return result;
|
||||
}
|
||||
|
||||
json::JsonObject AppliedZonesetsJSON::ToJson(const TDeviceInfoMap& deviceInfoMap, const GUID& currentVirtualDesktop)
|
||||
json::JsonObject EditorArgs::ToJson(const EditorArgs& args)
|
||||
{
|
||||
json::JsonObject result{};
|
||||
|
||||
json::JsonArray array;
|
||||
for (const auto& info : deviceInfoMap)
|
||||
result.SetNamedValue(NonLocalizable::ProcessId, json::value(args.processId));
|
||||
result.SetNamedValue(NonLocalizable::SpanZonesAcrossMonitors, json::value(args.spanZonesAcrossMonitors));
|
||||
|
||||
json::JsonArray monitors;
|
||||
for (const auto& monitor : args.monitors)
|
||||
{
|
||||
std::optional<FancyZonesDataTypes::DeviceIdData> id = FancyZonesUtils::ParseDeviceId(info.first);
|
||||
if (id.has_value() && id->virtualDesktopId == currentVirtualDesktop)
|
||||
{
|
||||
JSONHelpers::DeviceInfoJSON deviceInfoJson{ info.first, info.second };
|
||||
array.Append(JSONHelpers::DeviceInfoJSON::ToJson(deviceInfoJson));
|
||||
}
|
||||
monitors.Append(MonitorInfo::ToJson(monitor));
|
||||
}
|
||||
|
||||
result.SetNamedValue(NonLocalizable::AppliedZonesets, array);
|
||||
result.SetNamedValue(NonLocalizable::Monitors, monitors);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::optional<TDeviceInfoMap> AppliedZonesetsJSON::FromJson(const json::JsonObject& json)
|
||||
{
|
||||
try
|
||||
{
|
||||
TDeviceInfoMap appliedZonesets;
|
||||
|
||||
auto zonesets = json.GetNamedArray(NonLocalizable::AppliedZonesets);
|
||||
for (const auto& zoneset : zonesets)
|
||||
{
|
||||
std::optional<DeviceInfoJSON> device = DeviceInfoJSON::FromJson(zoneset.GetObjectW());
|
||||
if (device.has_value())
|
||||
{
|
||||
appliedZonesets.insert(std::make_pair(device->deviceId, device->data));
|
||||
}
|
||||
}
|
||||
|
||||
return appliedZonesets;
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
json::JsonObject GetPersistFancyZonesJSON(const std::wstring& zonesSettingsFileName, const std::wstring& appZoneHistoryFileName)
|
||||
{
|
||||
auto result = json::from_file(zonesSettingsFileName);
|
||||
@@ -534,12 +529,27 @@ namespace JSONHelpers
|
||||
|
||||
void SaveZoneSettings(const std::wstring& zonesSettingsFileName, const TDeviceInfoMap& deviceInfoMap, const TCustomZoneSetsMap& customZoneSetsMap)
|
||||
{
|
||||
json::JsonObject root{};
|
||||
auto before = json::from_file(zonesSettingsFileName);
|
||||
|
||||
json::JsonObject root{};
|
||||
json::JsonArray templates{};
|
||||
|
||||
try
|
||||
{
|
||||
if (before.has_value() && before->HasKey(NonLocalizable::Templates))
|
||||
{
|
||||
templates = before->GetNamedArray(NonLocalizable::Templates);
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
root.SetNamedValue(NonLocalizable::DevicesStr, JSONHelpers::SerializeDeviceInfos(deviceInfoMap));
|
||||
root.SetNamedValue(NonLocalizable::CustomZoneSetsStr, JSONHelpers::SerializeCustomZoneSets(customZoneSetsMap));
|
||||
|
||||
auto before = json::from_file(zonesSettingsFileName);
|
||||
root.SetNamedValue(NonLocalizable::Templates, templates);
|
||||
|
||||
if (!before.has_value() || before.value().Stringify() != root.Stringify())
|
||||
{
|
||||
Trace::FancyZones::DataChanged();
|
||||
@@ -665,104 +675,4 @@ namespace JSONHelpers
|
||||
|
||||
return customZoneSetsJSON;
|
||||
}
|
||||
|
||||
void SerializeDeviceInfoToTmpFile(const TDeviceInfoMap& deviceInfoMap, const GUID& currentVirtualDesktop, std::wstring_view tmpFilePath)
|
||||
{
|
||||
json::to_file(tmpFilePath, JSONHelpers::AppliedZonesetsJSON::ToJson(deviceInfoMap, currentVirtualDesktop));
|
||||
}
|
||||
|
||||
void SerializeCustomZoneSetsToTmpFile(const TCustomZoneSetsMap& customZoneSetsMap, std::wstring_view tmpFilePath)
|
||||
{
|
||||
json::JsonObject result{};
|
||||
|
||||
json::JsonArray array;
|
||||
for (const auto& zoneSet : customZoneSetsMap)
|
||||
{
|
||||
CustomZoneSetJSON json{ zoneSet.first, zoneSet.second };
|
||||
array.Append(JSONHelpers::CustomZoneSetJSON::ToJson(json));
|
||||
}
|
||||
|
||||
result.SetNamedValue(NonLocalizable::CreatedCustomZoneSets, array);
|
||||
json::to_file(tmpFilePath, result);
|
||||
}
|
||||
|
||||
std::optional<TDeviceInfoMap> ParseDeviceInfoFromTmpFile(std::wstring_view tmpFilePath)
|
||||
{
|
||||
std::optional<TDeviceInfoMap> result{ std::nullopt };
|
||||
if (std::filesystem::exists(tmpFilePath))
|
||||
{
|
||||
if (auto zoneSetJson = json::from_file(tmpFilePath); zoneSetJson.has_value())
|
||||
{
|
||||
if (auto deviceInfo = JSONHelpers::AppliedZonesetsJSON::FromJson(zoneSetJson.value()); deviceInfo.has_value())
|
||||
{
|
||||
result = std::move(deviceInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::trace(L"ParseDeviceInfoFromTmpFile: AppliedZonesetsJSON::FromJson parsing error, {}", zoneSetJson.value().Stringify());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DeleteTmpFile(tmpFilePath);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<CustomZoneSetJSON> ParseCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath)
|
||||
{
|
||||
std::vector<CustomZoneSetJSON> result;
|
||||
if (std::filesystem::exists(tmpFilePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (auto customZoneSetJson = json::from_file(tmpFilePath); customZoneSetJson.has_value())
|
||||
{
|
||||
auto zoneSetArray = customZoneSetJson.value().GetNamedArray(NonLocalizable::CreatedCustomZoneSets);
|
||||
for (const auto& zoneSet : zoneSetArray)
|
||||
{
|
||||
if (auto customZoneSet = JSONHelpers::CustomZoneSetJSON::FromJson(zoneSet.GetObjectW()); customZoneSet.has_value())
|
||||
{
|
||||
result.emplace_back(std::move(*customZoneSet));
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::trace(L"ParseCustomZoneSetsFromTmpFile: CustomZoneSetJSON::FromJson parsing error, {}", zoneSet.GetObjectW().Stringify());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error& err)
|
||||
{
|
||||
Logger::trace(L"ParseCustomZoneSetsFromTmpFile: CustomZoneSetJSON::FromJson parsing error, {}", err.message());
|
||||
}
|
||||
|
||||
DeleteTmpFile(tmpFilePath);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::wstring> ParseDeletedCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath)
|
||||
{
|
||||
std::vector<std::wstring> result{};
|
||||
if (std::filesystem::exists(tmpFilePath))
|
||||
{
|
||||
auto deletedZoneSetsJson = json::from_file(tmpFilePath);
|
||||
try
|
||||
{
|
||||
auto deletedCustomZoneSets = deletedZoneSetsJson->GetNamedArray(NonLocalizable::DeletedCustomZoneSetsStr);
|
||||
for (auto zoneSet : deletedCustomZoneSets)
|
||||
{
|
||||
std::wstring uuid = L"{" + std::wstring{ zoneSet.GetString() } + L"}";
|
||||
result.push_back(uuid);
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
{
|
||||
}
|
||||
|
||||
DeleteTmpFile(tmpFilePath);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -59,11 +59,24 @@ namespace JSONHelpers
|
||||
using TDeviceInfoMap = std::unordered_map<std::wstring, FancyZonesDataTypes::DeviceInfoData>;
|
||||
using TCustomZoneSetsMap = std::unordered_map<std::wstring, FancyZonesDataTypes::CustomZoneSetData>;
|
||||
|
||||
struct AppliedZonesetsJSON
|
||||
struct MonitorInfo
|
||||
{
|
||||
static json::JsonObject ToJson(const TDeviceInfoMap& deviceInfoMap);
|
||||
static json::JsonObject ToJson(const TDeviceInfoMap& deviceInfoMap, const GUID& currentVirtualDesktop);
|
||||
static std::optional<TDeviceInfoMap> FromJson(const json::JsonObject& json);
|
||||
int dpi;
|
||||
std::wstring id;
|
||||
int top;
|
||||
int left;
|
||||
bool isSelected = false;
|
||||
|
||||
static json::JsonObject ToJson(const MonitorInfo& monitor);
|
||||
};
|
||||
|
||||
struct EditorArgs
|
||||
{
|
||||
DWORD processId;
|
||||
bool spanZonesAcrossMonitors;
|
||||
std::vector<MonitorInfo> monitors;
|
||||
|
||||
static json::JsonObject ToJson(const EditorArgs& args);
|
||||
};
|
||||
|
||||
json::JsonObject GetPersistFancyZonesJSON(const std::wstring& zonesSettingsFileName, const std::wstring& appZoneHistoryFileName);
|
||||
@@ -79,14 +92,4 @@ namespace JSONHelpers
|
||||
|
||||
TCustomZoneSetsMap ParseCustomZoneSets(const json::JsonObject& fancyZonesDataJSON);
|
||||
json::JsonArray SerializeCustomZoneSets(const TCustomZoneSetsMap& customZoneSetsMap);
|
||||
|
||||
void SerializeDeviceInfoToTmpFile(const TDeviceInfoMap& deviceInfoMap, const GUID& currentVirtualDesktop, std::wstring_view tmpFilePath);
|
||||
std::optional<TDeviceInfoMap> ParseDeviceInfoFromTmpFile(std::wstring_view tmpFilePath);
|
||||
std::vector<CustomZoneSetJSON> ParseCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath);
|
||||
std::vector<std::wstring> ParseDeletedCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath);
|
||||
|
||||
#if defined(UNIT_TESTS)
|
||||
void SerializeCustomZoneSetsToTmpFile(const TCustomZoneSetsMap& customZoneSetsMap, std::wstring_view tmpFilePath);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user