mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-09 04:37:30 +02:00
[FancyZones] Split zones-settings: custom layouts (#15642)
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
#include <common/SettingsAPI/FileWatcher.h>
|
#include <common/SettingsAPI/FileWatcher.h>
|
||||||
|
|
||||||
#include <FancyZonesLib/FancyZonesData.h>
|
#include <FancyZonesLib/FancyZonesData.h>
|
||||||
|
#include <FancyZonesLib/FancyZonesData/CustomLayouts.h>
|
||||||
#include <FancyZonesLib/FancyZonesData/LayoutHotkeys.h>
|
#include <FancyZonesLib/FancyZonesData/LayoutHotkeys.h>
|
||||||
#include <FancyZonesLib/FancyZonesWindowProperties.h>
|
#include <FancyZonesLib/FancyZonesWindowProperties.h>
|
||||||
#include <FancyZonesLib/FancyZonesWinHookEventIDs.h>
|
#include <FancyZonesLib/FancyZonesWinHookEventIDs.h>
|
||||||
@@ -72,6 +73,7 @@ public:
|
|||||||
|
|
||||||
FancyZonesDataInstance().ReplaceZoneSettingsFileFromOlderVersions();
|
FancyZonesDataInstance().ReplaceZoneSettingsFileFromOlderVersions();
|
||||||
LayoutHotkeys::instance().LoadData();
|
LayoutHotkeys::instance().LoadData();
|
||||||
|
CustomLayouts::instance().LoadData();
|
||||||
}
|
}
|
||||||
|
|
||||||
// IFancyZones
|
// IFancyZones
|
||||||
@@ -775,6 +777,10 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
|
|||||||
{
|
{
|
||||||
LayoutHotkeys::instance().LoadData();
|
LayoutHotkeys::instance().LoadData();
|
||||||
}
|
}
|
||||||
|
else if (message == WM_PRIV_CUSTOM_LAYOUTS_FILE_UPDATE)
|
||||||
|
{
|
||||||
|
CustomLayouts::instance().LoadData();
|
||||||
|
}
|
||||||
else if (message == WM_PRIV_QUICK_LAYOUT_KEY)
|
else if (message == WM_PRIV_QUICK_LAYOUT_KEY)
|
||||||
{
|
{
|
||||||
ApplyQuickLayout(static_cast<int>(lparam));
|
ApplyQuickLayout(static_cast<int>(lparam));
|
||||||
@@ -1307,23 +1313,22 @@ void FancyZones::ApplyQuickLayout(int key) noexcept
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find a custom zone set with this uuid and apply it
|
||||||
|
auto layout = CustomLayouts::instance().GetLayout(layoutId.value());
|
||||||
|
if (!layout)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto uuidStr = FancyZonesUtils::GuidToString(layoutId.value());
|
auto uuidStr = FancyZonesUtils::GuidToString(layoutId.value());
|
||||||
if (!uuidStr)
|
if (!uuidStr)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto workArea = m_workAreaHandler.GetWorkAreaFromCursor(m_currentDesktopId);
|
|
||||||
|
|
||||||
// Find a custom zone set with this uuid and apply it
|
|
||||||
auto customZoneSets = FancyZonesDataInstance().GetCustomZoneSetsMap();
|
|
||||||
|
|
||||||
if (!customZoneSets.contains(uuidStr.value()))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FancyZonesDataTypes::ZoneSetData data{ .uuid = uuidStr.value(), .type = FancyZonesDataTypes::ZoneSetLayoutType::Custom };
|
FancyZonesDataTypes::ZoneSetData data{ .uuid = uuidStr.value(), .type = FancyZonesDataTypes::ZoneSetLayoutType::Custom };
|
||||||
|
|
||||||
|
auto workArea = m_workAreaHandler.GetWorkAreaFromCursor(m_currentDesktopId);
|
||||||
FancyZonesDataInstance().SetActiveZoneSet(workArea->UniqueId(), data);
|
FancyZonesDataInstance().SetActiveZoneSet(workArea->UniqueId(), data);
|
||||||
FancyZonesDataInstance().SaveZoneSettings();
|
FancyZonesDataInstance().SaveZoneSettings();
|
||||||
UpdateZoneSets();
|
UpdateZoneSets();
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include <common/utils/process_path.h>
|
#include <common/utils/process_path.h>
|
||||||
#include <common/logger/logger.h>
|
#include <common/logger/logger.h>
|
||||||
|
|
||||||
|
#include <FancyZonesLib/FancyZonesData/CustomLayouts.h>
|
||||||
#include <FancyZonesLib/FancyZonesData/LayoutHotkeys.h>
|
#include <FancyZonesLib/FancyZonesData/LayoutHotkeys.h>
|
||||||
#include <FancyZonesLib/ModuleConstants.h>
|
#include <FancyZonesLib/ModuleConstants.h>
|
||||||
|
|
||||||
@@ -170,6 +171,12 @@ void FancyZonesData::ReplaceZoneSettingsFileFromOlderVersions()
|
|||||||
//deviceInfoMap = JSONHelpers::ParseDeviceInfos(fancyZonesDataJSON);
|
//deviceInfoMap = JSONHelpers::ParseDeviceInfos(fancyZonesDataJSON);
|
||||||
//customZoneSetsMap = JSONHelpers::ParseCustomZoneSets(fancyZonesDataJSON);
|
//customZoneSetsMap = JSONHelpers::ParseCustomZoneSets(fancyZonesDataJSON);
|
||||||
|
|
||||||
|
auto customLayouts = JSONHelpers::ParseCustomZoneSets(fancyZonesDataJSON);
|
||||||
|
if (customLayouts)
|
||||||
|
{
|
||||||
|
JSONHelpers::SaveCustomLayouts(customLayouts.value());
|
||||||
|
}
|
||||||
|
|
||||||
auto templates = JSONHelpers::ParseLayoutTemplates(fancyZonesDataJSON);
|
auto templates = JSONHelpers::ParseLayoutTemplates(fancyZonesDataJSON);
|
||||||
if (templates)
|
if (templates)
|
||||||
{
|
{
|
||||||
@@ -197,12 +204,6 @@ const JSONHelpers::TDeviceInfoMap& FancyZonesData::GetDeviceInfoMap() const
|
|||||||
return deviceInfoMap;
|
return deviceInfoMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
const JSONHelpers::TCustomZoneSetsMap& FancyZonesData::GetCustomZoneSetsMap() const
|
|
||||||
{
|
|
||||||
std::scoped_lock lock{ dataLock };
|
|
||||||
return customZoneSetsMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>>& FancyZonesData::GetAppZoneHistoryMap() const
|
const std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>>& FancyZonesData::GetAppZoneHistoryMap() const
|
||||||
{
|
{
|
||||||
std::scoped_lock lock{ dataLock };
|
std::scoped_lock lock{ dataLock };
|
||||||
@@ -223,13 +224,6 @@ std::optional<FancyZonesDataTypes::DeviceInfoData> FancyZonesData::FindDeviceInf
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<FancyZonesDataTypes::CustomZoneSetData> FancyZonesData::FindCustomZoneSet(const std::wstring& guid) const
|
|
||||||
{
|
|
||||||
std::scoped_lock lock{ dataLock };
|
|
||||||
auto it = customZoneSetsMap.find(guid);
|
|
||||||
return it != end(customZoneSetsMap) ? std::optional{ it->second } : std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FancyZonesData::AddDevice(const FancyZonesDataTypes::DeviceIdData& deviceId)
|
bool FancyZonesData::AddDevice(const FancyZonesDataTypes::DeviceIdData& deviceId)
|
||||||
{
|
{
|
||||||
_TRACER_;
|
_TRACER_;
|
||||||
@@ -604,25 +598,29 @@ void FancyZonesData::SetActiveZoneSet(const FancyZonesDataTypes::DeviceIdData& d
|
|||||||
deviceInfo.activeZoneSet = data;
|
deviceInfo.activeZoneSet = data;
|
||||||
|
|
||||||
// If the zone set is custom, we need to copy its properties to the device
|
// If the zone set is custom, we need to copy its properties to the device
|
||||||
auto zonesetIt = customZoneSetsMap.find(data.uuid);
|
auto id = FancyZonesUtils::GuidFromString(data.uuid);
|
||||||
if (zonesetIt != customZoneSetsMap.end())
|
if (id.has_value())
|
||||||
{
|
{
|
||||||
if (zonesetIt->second.type == FancyZonesDataTypes::CustomLayoutType::Grid)
|
auto layout = CustomLayouts::instance().GetLayout(id.value());
|
||||||
|
if (layout)
|
||||||
{
|
{
|
||||||
auto layoutInfo = std::get<FancyZonesDataTypes::GridLayoutInfo>(zonesetIt->second.info);
|
if (layout.value().type == FancyZonesDataTypes::CustomLayoutType::Grid)
|
||||||
deviceInfo.sensitivityRadius = layoutInfo.sensitivityRadius();
|
{
|
||||||
deviceInfo.showSpacing = layoutInfo.showSpacing();
|
auto layoutInfo = std::get<FancyZonesDataTypes::GridLayoutInfo>(layout.value().info);
|
||||||
deviceInfo.spacing = layoutInfo.spacing();
|
deviceInfo.sensitivityRadius = layoutInfo.sensitivityRadius();
|
||||||
deviceInfo.zoneCount = layoutInfo.zoneCount();
|
deviceInfo.showSpacing = layoutInfo.showSpacing();
|
||||||
}
|
deviceInfo.spacing = layoutInfo.spacing();
|
||||||
else if (zonesetIt->second.type == FancyZonesDataTypes::CustomLayoutType::Canvas)
|
deviceInfo.zoneCount = layoutInfo.zoneCount();
|
||||||
{
|
}
|
||||||
auto layoutInfo = std::get<FancyZonesDataTypes::CanvasLayoutInfo>(zonesetIt->second.info);
|
else if (layout.value().type == FancyZonesDataTypes::CustomLayoutType::Canvas)
|
||||||
deviceInfo.sensitivityRadius = layoutInfo.sensitivityRadius;
|
{
|
||||||
deviceInfo.zoneCount = (int)layoutInfo.zones.size();
|
auto layoutInfo = std::get<FancyZonesDataTypes::CanvasLayoutInfo>(layout.value().info);
|
||||||
|
deviceInfo.sensitivityRadius = layoutInfo.sensitivityRadius;
|
||||||
|
deviceInfo.zoneCount = (int)layoutInfo.zones.size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -644,8 +642,7 @@ void FancyZonesData::LoadFancyZonesData()
|
|||||||
json::JsonObject fancyZonesDataJSON = GetPersistFancyZonesJSON();
|
json::JsonObject fancyZonesDataJSON = GetPersistFancyZonesJSON();
|
||||||
|
|
||||||
appZoneHistoryMap = JSONHelpers::ParseAppZoneHistory(fancyZonesDataJSON);
|
appZoneHistoryMap = JSONHelpers::ParseAppZoneHistory(fancyZonesDataJSON);
|
||||||
deviceInfoMap = JSONHelpers::ParseDeviceInfos(fancyZonesDataJSON);
|
deviceInfoMap = JSONHelpers::ParseDeviceInfos(fancyZonesDataJSON);
|
||||||
customZoneSetsMap = JSONHelpers::ParseCustomZoneSets(fancyZonesDataJSON);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -679,11 +676,11 @@ void FancyZonesData::SaveZoneSettings() const
|
|||||||
|
|
||||||
if (dirtyFlag)
|
if (dirtyFlag)
|
||||||
{
|
{
|
||||||
JSONHelpers::SaveZoneSettings(zonesSettingsFileName, updatedDeviceInfoMap, customZoneSetsMap);
|
JSONHelpers::SaveZoneSettings(zonesSettingsFileName, updatedDeviceInfoMap);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
JSONHelpers::SaveZoneSettings(zonesSettingsFileName, deviceInfoMap, customZoneSetsMap);
|
JSONHelpers::SaveZoneSettings(zonesSettingsFileName, deviceInfoMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace FancyZonesDataTypes
|
|||||||
struct ZoneSetData;
|
struct ZoneSetData;
|
||||||
struct DeviceIdData;
|
struct DeviceIdData;
|
||||||
struct DeviceInfoData;
|
struct DeviceInfoData;
|
||||||
struct CustomZoneSetData;
|
struct CustomLayoutData;
|
||||||
struct AppZoneHistoryData;
|
struct AppZoneHistoryData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,6 +32,7 @@ namespace FancyZonesUnitTests
|
|||||||
class WorkAreaCreationUnitTests;
|
class WorkAreaCreationUnitTests;
|
||||||
class LayoutHotkeysUnitTests;
|
class LayoutHotkeysUnitTests;
|
||||||
class LayoutTemplatesUnitTests;
|
class LayoutTemplatesUnitTests;
|
||||||
|
class CustomLayoutsUnitTests;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -45,10 +46,8 @@ public:
|
|||||||
void SetVirtualDesktopCheckCallback(std::function<bool(GUID)> callback);
|
void SetVirtualDesktopCheckCallback(std::function<bool(GUID)> callback);
|
||||||
|
|
||||||
std::optional<FancyZonesDataTypes::DeviceInfoData> FindDeviceInfo(const FancyZonesDataTypes::DeviceIdData& id) const;
|
std::optional<FancyZonesDataTypes::DeviceInfoData> FindDeviceInfo(const FancyZonesDataTypes::DeviceIdData& id) const;
|
||||||
std::optional<FancyZonesDataTypes::CustomZoneSetData> FindCustomZoneSet(const std::wstring& guid) const;
|
|
||||||
|
|
||||||
const JSONHelpers::TDeviceInfoMap& GetDeviceInfoMap() const;
|
const JSONHelpers::TDeviceInfoMap& GetDeviceInfoMap() const;
|
||||||
const JSONHelpers::TCustomZoneSetsMap& GetCustomZoneSetsMap() const;
|
|
||||||
const std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>>& GetAppZoneHistoryMap() const;
|
const std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>>& GetAppZoneHistoryMap() const;
|
||||||
|
|
||||||
inline const std::wstring& GetZonesSettingsFileName() const
|
inline const std::wstring& GetZonesSettingsFileName() const
|
||||||
@@ -92,17 +91,13 @@ private:
|
|||||||
friend class FancyZonesUnitTests::ZoneSetCalculateZonesUnitTests;
|
friend class FancyZonesUnitTests::ZoneSetCalculateZonesUnitTests;
|
||||||
friend class FancyZonesUnitTests::LayoutHotkeysUnitTests;
|
friend class FancyZonesUnitTests::LayoutHotkeysUnitTests;
|
||||||
friend class FancyZonesUnitTests::LayoutTemplatesUnitTests;
|
friend class FancyZonesUnitTests::LayoutTemplatesUnitTests;
|
||||||
|
friend class FancyZonesUnitTests::CustomLayoutsUnitTests;
|
||||||
|
|
||||||
inline void SetDeviceInfo(const FancyZonesDataTypes::DeviceIdData& deviceId, FancyZonesDataTypes::DeviceInfoData data)
|
inline void SetDeviceInfo(const FancyZonesDataTypes::DeviceIdData& deviceId, FancyZonesDataTypes::DeviceInfoData data)
|
||||||
{
|
{
|
||||||
deviceInfoMap[deviceId] = data;
|
deviceInfoMap[deviceId] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SetCustomZonesets(const std::wstring& uuid, FancyZonesDataTypes::CustomZoneSetData data)
|
|
||||||
{
|
|
||||||
customZoneSetsMap[uuid] = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool ParseDeviceInfos(const json::JsonObject& fancyZonesDataJSON)
|
inline bool ParseDeviceInfos(const json::JsonObject& fancyZonesDataJSON)
|
||||||
{
|
{
|
||||||
deviceInfoMap = JSONHelpers::ParseDeviceInfos(fancyZonesDataJSON);
|
deviceInfoMap = JSONHelpers::ParseDeviceInfos(fancyZonesDataJSON);
|
||||||
@@ -113,7 +108,6 @@ private:
|
|||||||
{
|
{
|
||||||
appZoneHistoryMap.clear();
|
appZoneHistoryMap.clear();
|
||||||
deviceInfoMap.clear();
|
deviceInfoMap.clear();
|
||||||
customZoneSetsMap.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SetSettingsModulePath(std::wstring_view moduleName)
|
inline void SetSettingsModulePath(std::wstring_view moduleName)
|
||||||
@@ -135,8 +129,6 @@ private:
|
|||||||
std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>> appZoneHistoryMap{};
|
std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>> appZoneHistoryMap{};
|
||||||
// Maps device unique ID to device data
|
// Maps device unique ID to device data
|
||||||
JSONHelpers::TDeviceInfoMap deviceInfoMap{};
|
JSONHelpers::TDeviceInfoMap deviceInfoMap{};
|
||||||
// Maps custom zoneset UUID to it's data
|
|
||||||
JSONHelpers::TCustomZoneSetsMap customZoneSetsMap{};
|
|
||||||
|
|
||||||
std::wstring settingsFileName;
|
std::wstring settingsFileName;
|
||||||
std::wstring zonesSettingsFileName;
|
std::wstring zonesSettingsFileName;
|
||||||
|
|||||||
@@ -0,0 +1,233 @@
|
|||||||
|
#include "../pch.h"
|
||||||
|
#include "CustomLayouts.h"
|
||||||
|
|
||||||
|
#include <common/logger/logger.h>
|
||||||
|
|
||||||
|
#include <FancyZonesLib/FancyZonesData.h> // layout defaults
|
||||||
|
#include <FancyZonesLib/FancyZonesWinHookEventIDs.h>
|
||||||
|
#include <FancyZonesLib/JsonHelpers.h>
|
||||||
|
#include <FancyZonesLib/util.h>
|
||||||
|
|
||||||
|
namespace JsonUtils
|
||||||
|
{
|
||||||
|
std::vector<int> JsonArrayToNumVec(const json::JsonArray& arr)
|
||||||
|
{
|
||||||
|
std::vector<int> vec;
|
||||||
|
for (const auto& val : arr)
|
||||||
|
{
|
||||||
|
vec.emplace_back(static_cast<int>(val.GetNumber()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CanvasLayoutInfoJSON
|
||||||
|
{
|
||||||
|
std::optional<FancyZonesDataTypes::CanvasLayoutInfo> FromJson(const json::JsonObject& infoJson)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FancyZonesDataTypes::CanvasLayoutInfo info;
|
||||||
|
info.lastWorkAreaWidth = static_cast<int>(infoJson.GetNamedNumber(NonLocalizable::CustomLayoutsIds::RefWidthID));
|
||||||
|
info.lastWorkAreaHeight = static_cast<int>(infoJson.GetNamedNumber(NonLocalizable::CustomLayoutsIds::RefHeightID));
|
||||||
|
|
||||||
|
json::JsonArray zonesJson = infoJson.GetNamedArray(NonLocalizable::CustomLayoutsIds::ZonesID);
|
||||||
|
uint32_t size = zonesJson.Size();
|
||||||
|
info.zones.reserve(size);
|
||||||
|
for (uint32_t i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
json::JsonObject zoneJson = zonesJson.GetObjectAt(i);
|
||||||
|
const int x = static_cast<int>(zoneJson.GetNamedNumber(NonLocalizable::CustomLayoutsIds::XID));
|
||||||
|
const int y = static_cast<int>(zoneJson.GetNamedNumber(NonLocalizable::CustomLayoutsIds::YID));
|
||||||
|
const int width = static_cast<int>(zoneJson.GetNamedNumber(NonLocalizable::CustomLayoutsIds::WidthID));
|
||||||
|
const int height = static_cast<int>(zoneJson.GetNamedNumber(NonLocalizable::CustomLayoutsIds::HeightID));
|
||||||
|
FancyZonesDataTypes::CanvasLayoutInfo::Rect zone{ x, y, width, height };
|
||||||
|
info.zones.push_back(zone);
|
||||||
|
}
|
||||||
|
|
||||||
|
info.sensitivityRadius = static_cast<int>(infoJson.GetNamedNumber(NonLocalizable::CustomLayoutsIds::SensitivityRadiusID, DefaultValues::SensitivityRadius));
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
catch (const winrt::hresult_error&)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace GridLayoutInfoJSON
|
||||||
|
{
|
||||||
|
std::optional<FancyZonesDataTypes::GridLayoutInfo> FromJson(const json::JsonObject& infoJson)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FancyZonesDataTypes::GridLayoutInfo info(FancyZonesDataTypes::GridLayoutInfo::Minimal{});
|
||||||
|
|
||||||
|
info.m_rows = static_cast<int>(infoJson.GetNamedNumber(NonLocalizable::CustomLayoutsIds::RowsID));
|
||||||
|
info.m_columns = static_cast<int>(infoJson.GetNamedNumber(NonLocalizable::CustomLayoutsIds::ColumnsID));
|
||||||
|
|
||||||
|
json::JsonArray rowsPercentage = infoJson.GetNamedArray(NonLocalizable::CustomLayoutsIds::RowsPercentageID);
|
||||||
|
json::JsonArray columnsPercentage = infoJson.GetNamedArray(NonLocalizable::CustomLayoutsIds::ColumnsPercentageID);
|
||||||
|
json::JsonArray cellChildMap = infoJson.GetNamedArray(NonLocalizable::CustomLayoutsIds::CellChildMapID);
|
||||||
|
|
||||||
|
if (rowsPercentage.Size() != info.m_rows || columnsPercentage.Size() != info.m_columns || cellChildMap.Size() != info.m_rows)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.m_rowsPercents = JsonArrayToNumVec(rowsPercentage);
|
||||||
|
info.m_columnsPercents = JsonArrayToNumVec(columnsPercentage);
|
||||||
|
for (const auto& cellsRow : cellChildMap)
|
||||||
|
{
|
||||||
|
const auto cellsArray = cellsRow.GetArray();
|
||||||
|
if (cellsArray.Size() != info.m_columns)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
info.cellChildMap().push_back(JsonArrayToNumVec(cellsArray));
|
||||||
|
}
|
||||||
|
|
||||||
|
info.m_showSpacing = infoJson.GetNamedBoolean(NonLocalizable::CustomLayoutsIds::ShowSpacingID, DefaultValues::ShowSpacing);
|
||||||
|
info.m_spacing = static_cast<int>(infoJson.GetNamedNumber(NonLocalizable::CustomLayoutsIds::SpacingID, DefaultValues::Spacing));
|
||||||
|
info.m_sensitivityRadius = static_cast<int>(infoJson.GetNamedNumber(NonLocalizable::CustomLayoutsIds::SensitivityRadiusID, DefaultValues::SensitivityRadius));
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
catch (const winrt::hresult_error&)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CustomLayoutJSON
|
||||||
|
{
|
||||||
|
GUID layoutId;
|
||||||
|
FancyZonesDataTypes::CustomLayoutData data;
|
||||||
|
|
||||||
|
static std::optional<CustomLayoutJSON> FromJson(const json::JsonObject& json)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CustomLayoutJSON result;
|
||||||
|
|
||||||
|
auto idStr = json.GetNamedString(NonLocalizable::CustomLayoutsIds::UuidID);
|
||||||
|
auto id = FancyZonesUtils::GuidFromString(idStr.c_str());
|
||||||
|
if (!id)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.layoutId = id.value();
|
||||||
|
result.data.name = json.GetNamedString(NonLocalizable::CustomLayoutsIds::NameID);
|
||||||
|
|
||||||
|
json::JsonObject infoJson = json.GetNamedObject(NonLocalizable::CustomLayoutsIds::InfoID);
|
||||||
|
std::wstring zoneSetType = std::wstring{ json.GetNamedString(NonLocalizable::CustomLayoutsIds::TypeID) };
|
||||||
|
if (zoneSetType.compare(NonLocalizable::CustomLayoutsIds::CanvasID) == 0)
|
||||||
|
{
|
||||||
|
if (auto info = CanvasLayoutInfoJSON::FromJson(infoJson); info.has_value())
|
||||||
|
{
|
||||||
|
result.data.type = FancyZonesDataTypes::CustomLayoutType::Canvas;
|
||||||
|
result.data.info = std::move(info.value());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (zoneSetType.compare(NonLocalizable::CustomLayoutsIds::GridID) == 0)
|
||||||
|
{
|
||||||
|
if (auto info = GridLayoutInfoJSON::FromJson(infoJson); info.has_value())
|
||||||
|
{
|
||||||
|
result.data.type = FancyZonesDataTypes::CustomLayoutType::Grid;
|
||||||
|
result.data.info = std::move(info.value());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (const winrt::hresult_error&)
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CustomLayouts::TCustomLayoutMap ParseJson(const json::JsonObject& json)
|
||||||
|
{
|
||||||
|
CustomLayouts::TCustomLayoutMap map{};
|
||||||
|
auto layouts = json.GetNamedArray(NonLocalizable::CustomLayoutsIds::CustomLayoutsArrayID);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < layouts.Size(); ++i)
|
||||||
|
{
|
||||||
|
if (auto obj = CustomLayoutJSON::FromJson(layouts.GetObjectAt(i)); obj.has_value())
|
||||||
|
{
|
||||||
|
map[obj->layoutId] = std::move(obj->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CustomLayouts::CustomLayouts()
|
||||||
|
{
|
||||||
|
const std::wstring& dataFileName = CustomLayoutsFileName();
|
||||||
|
m_fileWatcher = std::make_unique<FileWatcher>(dataFileName, [&]() {
|
||||||
|
PostMessageW(HWND_BROADCAST, WM_PRIV_CUSTOM_LAYOUTS_FILE_UPDATE, NULL, NULL);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CustomLayouts& CustomLayouts::instance()
|
||||||
|
{
|
||||||
|
static CustomLayouts self;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CustomLayouts::LoadData()
|
||||||
|
{
|
||||||
|
auto data = json::from_file(CustomLayoutsFileName());
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
m_layouts = JsonUtils::ParseJson(data.value());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_layouts.clear();
|
||||||
|
Logger::info(L"custom-layouts.json file is missing or malformed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const winrt::hresult_error& e)
|
||||||
|
{
|
||||||
|
Logger::error(L"Parsing custom-layouts error: {}", e.message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<FancyZonesDataTypes::CustomLayoutData> CustomLayouts::GetLayout(const GUID& id) const noexcept
|
||||||
|
{
|
||||||
|
auto iter = m_layouts.find(id);
|
||||||
|
if (iter != m_layouts.end())
|
||||||
|
{
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CustomLayouts::TCustomLayoutMap& CustomLayouts::GetAllLayouts() const noexcept
|
||||||
|
{
|
||||||
|
return m_layouts;
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <guiddef.h>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include <FancyZonesLib/FancyZonesDataTypes.h>
|
||||||
|
#include <FancyZonesLib/GuidUtils.h>
|
||||||
|
#include <FancyZonesLib/ModuleConstants.h>
|
||||||
|
|
||||||
|
#include <common/SettingsAPI/FileWatcher.h>
|
||||||
|
#include <common/SettingsAPI/settings_helpers.h>
|
||||||
|
|
||||||
|
namespace NonLocalizable
|
||||||
|
{
|
||||||
|
namespace CustomLayoutsIds
|
||||||
|
{
|
||||||
|
const static wchar_t* CustomLayoutsArrayID = L"custom-layouts";
|
||||||
|
const static wchar_t* UuidID = L"uuid";
|
||||||
|
const static wchar_t* NameID = L"name";
|
||||||
|
const static wchar_t* InfoID = L"info";
|
||||||
|
const static wchar_t* TypeID = L"type";
|
||||||
|
const static wchar_t* CanvasID = L"canvas";
|
||||||
|
const static wchar_t* GridID = L"grid";
|
||||||
|
const static wchar_t* SensitivityRadiusID = L"sensitivity-radius";
|
||||||
|
|
||||||
|
// canvas
|
||||||
|
const static wchar_t* RefHeightID = L"ref-height";
|
||||||
|
const static wchar_t* RefWidthID = L"ref-width";
|
||||||
|
const static wchar_t* ZonesID = L"zones";
|
||||||
|
const static wchar_t* XID = L"X";
|
||||||
|
const static wchar_t* YID = L"Y";
|
||||||
|
const static wchar_t* WidthID = L"width";
|
||||||
|
const static wchar_t* HeightID = L"height";
|
||||||
|
|
||||||
|
// grid
|
||||||
|
const static wchar_t* RowsID = L"rows";
|
||||||
|
const static wchar_t* ColumnsID = L"columns";
|
||||||
|
const static wchar_t* RowsPercentageID = L"rows-percentage";
|
||||||
|
const static wchar_t* ColumnsPercentageID = L"columns-percentage";
|
||||||
|
const static wchar_t* CellChildMapID = L"cell-child-map";
|
||||||
|
const static wchar_t* ShowSpacingID = L"show-spacing";
|
||||||
|
const static wchar_t* SpacingID = L"spacing";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomLayouts
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using TCustomLayoutMap = std::unordered_map<GUID, FancyZonesDataTypes::CustomLayoutData>;
|
||||||
|
|
||||||
|
static CustomLayouts& instance();
|
||||||
|
|
||||||
|
inline static std::wstring CustomLayoutsFileName()
|
||||||
|
{
|
||||||
|
std::wstring saveFolderPath = PTSettingsHelper::get_module_save_folder_location(NonLocalizable::ModuleKey);
|
||||||
|
#if defined(UNIT_TESTS)
|
||||||
|
return saveFolderPath + L"\\test-custom-layouts.json";
|
||||||
|
#endif
|
||||||
|
return saveFolderPath + L"\\custom-layouts.json";
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadData();
|
||||||
|
|
||||||
|
std::optional<FancyZonesDataTypes::CustomLayoutData> GetLayout(const GUID& id) const noexcept;
|
||||||
|
const TCustomLayoutMap& GetAllLayouts() const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CustomLayouts();
|
||||||
|
~CustomLayouts() = default;
|
||||||
|
|
||||||
|
TCustomLayoutMap m_layouts;
|
||||||
|
std::unique_ptr<FileWatcher> m_fileWatcher;
|
||||||
|
};
|
||||||
@@ -100,7 +100,7 @@ namespace FancyZonesDataTypes
|
|||||||
int m_sensitivityRadius;
|
int m_sensitivityRadius;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CustomZoneSetData
|
struct CustomLayoutData
|
||||||
{
|
{
|
||||||
std::wstring name;
|
std::wstring name;
|
||||||
CustomLayoutType type;
|
CustomLayoutType type;
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="FancyZonesData\CustomLayouts.h" />
|
||||||
<ClInclude Include="FancyZones.h" />
|
<ClInclude Include="FancyZones.h" />
|
||||||
<ClInclude Include="FancyZonesDataTypes.h" />
|
<ClInclude Include="FancyZonesDataTypes.h" />
|
||||||
<ClInclude Include="FancyZonesData\LayoutTemplates.h" />
|
<ClInclude Include="FancyZonesData\LayoutTemplates.h" />
|
||||||
@@ -67,6 +68,10 @@
|
|||||||
<ClInclude Include="ZonesOverlay.h" />
|
<ClInclude Include="ZonesOverlay.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="FancyZonesData\CustomLayouts.cpp">
|
||||||
|
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../pch.h</PrecompiledHeaderFile>
|
||||||
|
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../pch.h</PrecompiledHeaderFile>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="FancyZones.cpp" />
|
<ClCompile Include="FancyZones.cpp" />
|
||||||
<ClCompile Include="FancyZonesDataTypes.cpp" />
|
<ClCompile Include="FancyZonesDataTypes.cpp" />
|
||||||
<ClCompile Include="FancyZonesWinHookEventIDs.cpp" />
|
<ClCompile Include="FancyZonesWinHookEventIDs.cpp" />
|
||||||
|
|||||||
@@ -90,6 +90,9 @@
|
|||||||
<ClInclude Include="GuidUtils.h">
|
<ClInclude Include="GuidUtils.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="FancyZonesData\CustomLayouts.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="FancyZonesData\LayoutHotkeys.h">
|
<ClInclude Include="FancyZonesData\LayoutHotkeys.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -158,6 +161,9 @@
|
|||||||
<ClCompile Include="MonitorUtils.cpp">
|
<ClCompile Include="MonitorUtils.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="FancyZonesData\CustomLayouts.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="FancyZonesData\LayoutHotkeys.cpp">
|
<ClCompile Include="FancyZonesData\LayoutHotkeys.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ UINT WM_PRIV_VD_UPDATE;
|
|||||||
UINT WM_PRIV_EDITOR;
|
UINT WM_PRIV_EDITOR;
|
||||||
UINT WM_PRIV_FILE_UPDATE;
|
UINT WM_PRIV_FILE_UPDATE;
|
||||||
UINT WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE;
|
UINT WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE;
|
||||||
|
UINT WM_PRIV_CUSTOM_LAYOUTS_FILE_UPDATE;
|
||||||
UINT WM_PRIV_SNAP_HOTKEY;
|
UINT WM_PRIV_SNAP_HOTKEY;
|
||||||
UINT WM_PRIV_QUICK_LAYOUT_KEY;
|
UINT WM_PRIV_QUICK_LAYOUT_KEY;
|
||||||
UINT WM_PRIV_SETTINGS_CHANGED;
|
UINT WM_PRIV_SETTINGS_CHANGED;
|
||||||
@@ -33,6 +34,7 @@ void InitializeWinhookEventIds()
|
|||||||
WM_PRIV_EDITOR = RegisterWindowMessage(L"{87543824-7080-4e91-9d9c-0404642fc7b6}");
|
WM_PRIV_EDITOR = RegisterWindowMessage(L"{87543824-7080-4e91-9d9c-0404642fc7b6}");
|
||||||
WM_PRIV_FILE_UPDATE = RegisterWindowMessage(L"{632f17a9-55a7-45f1-a4db-162e39271d92}");
|
WM_PRIV_FILE_UPDATE = RegisterWindowMessage(L"{632f17a9-55a7-45f1-a4db-162e39271d92}");
|
||||||
WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE = RegisterWindowMessage(L"{07229b7e-4f22-4357-b136-33c289be2295}");
|
WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE = RegisterWindowMessage(L"{07229b7e-4f22-4357-b136-33c289be2295}");
|
||||||
|
WM_PRIV_CUSTOM_LAYOUTS_FILE_UPDATE = RegisterWindowMessage(L"{0972787e-cdab-4e16-b228-91acdc38f40f}");
|
||||||
WM_PRIV_SNAP_HOTKEY = RegisterWindowMessage(L"{72f4fd8e-23f1-43ab-bbbc-029363df9a84}");
|
WM_PRIV_SNAP_HOTKEY = RegisterWindowMessage(L"{72f4fd8e-23f1-43ab-bbbc-029363df9a84}");
|
||||||
WM_PRIV_QUICK_LAYOUT_KEY = RegisterWindowMessage(L"{15baab3d-c67b-4a15-aFF0-13610e05e947}");
|
WM_PRIV_QUICK_LAYOUT_KEY = RegisterWindowMessage(L"{15baab3d-c67b-4a15-aFF0-13610e05e947}");
|
||||||
WM_PRIV_SETTINGS_CHANGED = RegisterWindowMessage(L"{89ca3Daa-bf2d-4e73-9f3f-c60716364e27}");
|
WM_PRIV_SETTINGS_CHANGED = RegisterWindowMessage(L"{89ca3Daa-bf2d-4e73-9f3f-c60716364e27}");
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ extern UINT WM_PRIV_VD_UPDATE; // Scheduled on virtual desktops update (creation
|
|||||||
extern UINT WM_PRIV_EDITOR; // Scheduled when the editor exits
|
extern UINT WM_PRIV_EDITOR; // Scheduled when the editor exits
|
||||||
extern UINT WM_PRIV_FILE_UPDATE; // Scheduled when the watched zone-settings file is updated
|
extern UINT WM_PRIV_FILE_UPDATE; // Scheduled when the watched zone-settings file is updated
|
||||||
extern UINT WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE; // Scheduled when the watched layout-hotkeys.json file is updated
|
extern UINT WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE; // Scheduled when the watched layout-hotkeys.json file is updated
|
||||||
|
extern UINT WM_PRIV_CUSTOM_LAYOUTS_FILE_UPDATE; // Scheduled when the watched custom-layouts.json file is updated
|
||||||
extern UINT WM_PRIV_SNAP_HOTKEY; // Scheduled when we receive a snap hotkey key down press
|
extern UINT WM_PRIV_SNAP_HOTKEY; // Scheduled when we receive a snap hotkey key down press
|
||||||
extern UINT WM_PRIV_QUICK_LAYOUT_KEY; // Scheduled when we receive a key down press to quickly apply a layout
|
extern UINT WM_PRIV_QUICK_LAYOUT_KEY; // Scheduled when we receive a key down press to quickly apply a layout
|
||||||
extern UINT WM_PRIV_SETTINGS_CHANGED; // Scheduled when the a watched settings file is updated
|
extern UINT WM_PRIV_SETTINGS_CHANGED; // Scheduled when the a watched settings file is updated
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
#include <FancyZonesLib/FancyZonesData/CustomLayouts.h>
|
||||||
#include <FancyZonesLib/FancyZonesData/LayoutHotkeys.h>
|
#include <FancyZonesLib/FancyZonesData/LayoutHotkeys.h>
|
||||||
#include <FancyZonesLib/FancyZonesData/LayoutTemplates.h>
|
#include <FancyZonesLib/FancyZonesData/LayoutTemplates.h>
|
||||||
|
|
||||||
@@ -579,14 +580,13 @@ namespace JSONHelpers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveZoneSettings(const std::wstring& zonesSettingsFileName, const TDeviceInfoMap& deviceInfoMap, const TCustomZoneSetsMap& customZoneSetsMap)
|
void SaveZoneSettings(const std::wstring& zonesSettingsFileName, const TDeviceInfoMap& deviceInfoMap)
|
||||||
{
|
{
|
||||||
auto before = json::from_file(zonesSettingsFileName);
|
auto before = json::from_file(zonesSettingsFileName);
|
||||||
|
|
||||||
json::JsonObject root{};
|
json::JsonObject root{};
|
||||||
|
|
||||||
root.SetNamedValue(NonLocalizable::DevicesStr, JSONHelpers::SerializeDeviceInfos(deviceInfoMap));
|
root.SetNamedValue(NonLocalizable::DevicesStr, JSONHelpers::SerializeDeviceInfos(deviceInfoMap));
|
||||||
root.SetNamedValue(NonLocalizable::CustomZoneSetsStr, JSONHelpers::SerializeCustomZoneSets(customZoneSetsMap));
|
|
||||||
|
|
||||||
if (!before.has_value() || before.value().Stringify() != root.Stringify())
|
if (!before.has_value() || before.value().Stringify() != root.Stringify())
|
||||||
{
|
{
|
||||||
@@ -679,29 +679,6 @@ namespace JSONHelpers
|
|||||||
return DeviceInfosJSON;
|
return DeviceInfosJSON;
|
||||||
}
|
}
|
||||||
|
|
||||||
TCustomZoneSetsMap ParseCustomZoneSets(const json::JsonObject& fancyZonesDataJSON)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
TCustomZoneSetsMap customZoneSetsMap{};
|
|
||||||
auto customZoneSets = fancyZonesDataJSON.GetNamedArray(NonLocalizable::CustomZoneSetsStr);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < customZoneSets.Size(); ++i)
|
|
||||||
{
|
|
||||||
if (auto zoneSet = CustomZoneSetJSON::FromJson(customZoneSets.GetObjectAt(i)); zoneSet.has_value())
|
|
||||||
{
|
|
||||||
customZoneSetsMap[zoneSet->uuid] = std::move(zoneSet->data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::move(customZoneSetsMap);
|
|
||||||
}
|
|
||||||
catch (const winrt::hresult_error&)
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
json::JsonArray SerializeCustomZoneSets(const TCustomZoneSetsMap& customZoneSetsMap)
|
json::JsonArray SerializeCustomZoneSets(const TCustomZoneSetsMap& customZoneSetsMap)
|
||||||
{
|
{
|
||||||
json::JsonArray customZoneSetsJSON{};
|
json::JsonArray customZoneSetsJSON{};
|
||||||
@@ -777,4 +754,43 @@ namespace JSONHelpers
|
|||||||
root.SetNamedValue(NonLocalizable::LayoutTemplatesIds::LayoutTemplatesArrayID, templates);
|
root.SetNamedValue(NonLocalizable::LayoutTemplatesIds::LayoutTemplatesArrayID, templates);
|
||||||
json::to_file(LayoutTemplates::LayoutTemplatesFileName(), root);
|
json::to_file(LayoutTemplates::LayoutTemplatesFileName(), root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<TCustomZoneSetsMap> ParseCustomZoneSets(const json::JsonObject& fancyZonesDataJSON)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TCustomZoneSetsMap customZoneSetsMap{};
|
||||||
|
auto customZoneSets = fancyZonesDataJSON.GetNamedArray(NonLocalizable::CustomZoneSetsStr);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < customZoneSets.Size(); ++i)
|
||||||
|
{
|
||||||
|
if (auto zoneSet = CustomZoneSetJSON::FromJson(customZoneSets.GetObjectAt(i)); zoneSet.has_value())
|
||||||
|
{
|
||||||
|
customZoneSetsMap[zoneSet->uuid] = std::move(zoneSet->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(customZoneSetsMap);
|
||||||
|
}
|
||||||
|
catch (const winrt::hresult_error& e)
|
||||||
|
{
|
||||||
|
Logger::error(L"Parsing custom layouts error: {}", e.message());
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveCustomLayouts(const TCustomZoneSetsMap& map)
|
||||||
|
{
|
||||||
|
json::JsonObject root{};
|
||||||
|
json::JsonArray layoutsArray{};
|
||||||
|
|
||||||
|
for (const auto& [uuid, data] : map)
|
||||||
|
{
|
||||||
|
json::JsonObject layoutJson{};
|
||||||
|
layoutsArray.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ uuid, data }));
|
||||||
|
}
|
||||||
|
|
||||||
|
root.SetNamedValue(NonLocalizable::CustomLayoutsIds::CustomLayoutsArrayID, layoutsArray);
|
||||||
|
json::to_file(CustomLayouts::CustomLayoutsFileName(), root);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@ namespace JSONHelpers
|
|||||||
struct CustomZoneSetJSON
|
struct CustomZoneSetJSON
|
||||||
{
|
{
|
||||||
std::wstring uuid;
|
std::wstring uuid;
|
||||||
FancyZonesDataTypes::CustomZoneSetData data;
|
FancyZonesDataTypes::CustomLayoutData data;
|
||||||
|
|
||||||
static json::JsonObject ToJson(const CustomZoneSetJSON& device);
|
static json::JsonObject ToJson(const CustomZoneSetJSON& device);
|
||||||
static std::optional<CustomZoneSetJSON> FromJson(const json::JsonObject& customZoneSet);
|
static std::optional<CustomZoneSetJSON> FromJson(const json::JsonObject& customZoneSet);
|
||||||
@@ -66,7 +66,7 @@ namespace JSONHelpers
|
|||||||
|
|
||||||
using TAppZoneHistoryMap = std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>>;
|
using TAppZoneHistoryMap = std::unordered_map<std::wstring, std::vector<FancyZonesDataTypes::AppZoneHistoryData>>;
|
||||||
using TDeviceInfoMap = std::unordered_map<FancyZonesDataTypes::DeviceIdData, FancyZonesDataTypes::DeviceInfoData>;
|
using TDeviceInfoMap = std::unordered_map<FancyZonesDataTypes::DeviceIdData, FancyZonesDataTypes::DeviceInfoData>;
|
||||||
using TCustomZoneSetsMap = std::unordered_map<std::wstring, FancyZonesDataTypes::CustomZoneSetData>;
|
using TCustomZoneSetsMap = std::unordered_map<std::wstring, FancyZonesDataTypes::CustomLayoutData>;
|
||||||
using TLayoutQuickKeysMap = std::unordered_map<std::wstring, int>;
|
using TLayoutQuickKeysMap = std::unordered_map<std::wstring, int>;
|
||||||
|
|
||||||
struct MonitorInfo
|
struct MonitorInfo
|
||||||
@@ -93,7 +93,7 @@ namespace JSONHelpers
|
|||||||
|
|
||||||
json::JsonObject GetPersistFancyZonesJSON(const std::wstring& zonesSettingsFileName, const std::wstring& appZoneHistoryFileName);
|
json::JsonObject GetPersistFancyZonesJSON(const std::wstring& zonesSettingsFileName, const std::wstring& appZoneHistoryFileName);
|
||||||
|
|
||||||
void SaveZoneSettings(const std::wstring& zonesSettingsFileName, const TDeviceInfoMap& deviceInfoMap, const TCustomZoneSetsMap& customZoneSetsMap);
|
void SaveZoneSettings(const std::wstring& zonesSettingsFileName, const TDeviceInfoMap& deviceInfoMap);
|
||||||
void SaveAppZoneHistory(const std::wstring& appZoneHistoryFileName, const TAppZoneHistoryMap& appZoneHistoryMap);
|
void SaveAppZoneHistory(const std::wstring& appZoneHistoryFileName, const TAppZoneHistoryMap& appZoneHistoryMap);
|
||||||
|
|
||||||
TAppZoneHistoryMap ParseAppZoneHistory(const json::JsonObject& fancyZonesDataJSON);
|
TAppZoneHistoryMap ParseAppZoneHistory(const json::JsonObject& fancyZonesDataJSON);
|
||||||
@@ -102,9 +102,6 @@ namespace JSONHelpers
|
|||||||
TDeviceInfoMap ParseDeviceInfos(const json::JsonObject& fancyZonesDataJSON);
|
TDeviceInfoMap ParseDeviceInfos(const json::JsonObject& fancyZonesDataJSON);
|
||||||
json::JsonArray SerializeDeviceInfos(const TDeviceInfoMap& deviceInfoMap);
|
json::JsonArray SerializeDeviceInfos(const TDeviceInfoMap& deviceInfoMap);
|
||||||
|
|
||||||
TCustomZoneSetsMap ParseCustomZoneSets(const json::JsonObject& fancyZonesDataJSON);
|
|
||||||
json::JsonArray SerializeCustomZoneSets(const TCustomZoneSetsMap& customZoneSetsMap);
|
|
||||||
|
|
||||||
// replace zones-settings: layout hotkeys
|
// replace zones-settings: layout hotkeys
|
||||||
std::optional<TLayoutQuickKeysMap> ParseQuickKeys(const json::JsonObject& fancyZonesDataJSON);
|
std::optional<TLayoutQuickKeysMap> ParseQuickKeys(const json::JsonObject& fancyZonesDataJSON);
|
||||||
void SaveLayoutHotkeys(const TLayoutQuickKeysMap& quickKeysMap);
|
void SaveLayoutHotkeys(const TLayoutQuickKeysMap& quickKeysMap);
|
||||||
@@ -112,4 +109,8 @@ namespace JSONHelpers
|
|||||||
// replace zones-settings: layout templates
|
// replace zones-settings: layout templates
|
||||||
std::optional<json::JsonArray> ParseLayoutTemplates(const json::JsonObject& fancyZonesDataJSON);
|
std::optional<json::JsonArray> ParseLayoutTemplates(const json::JsonObject& fancyZonesDataJSON);
|
||||||
void SaveLayoutTemplates(const json::JsonArray& templates);
|
void SaveLayoutTemplates(const json::JsonArray& templates);
|
||||||
|
|
||||||
|
// replace zones-settings: custom layouts
|
||||||
|
std::optional<TCustomZoneSetsMap> ParseCustomZoneSets(const json::JsonObject& fancyZonesDataJSON);
|
||||||
|
void SaveCustomLayouts(const TCustomZoneSetsMap& map);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "ZoneSet.h"
|
#include "ZoneSet.h"
|
||||||
|
|
||||||
#include "FancyZonesData.h"
|
#include "FancyZonesData.h"
|
||||||
|
#include <FancyZonesLib/FancyZonesData/CustomLayouts.h>
|
||||||
#include "FancyZonesDataTypes.h"
|
#include "FancyZonesDataTypes.h"
|
||||||
#include "FancyZonesWindowProperties.h"
|
#include "FancyZonesWindowProperties.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
@@ -880,52 +881,45 @@ bool ZoneSet::CalculateUniquePriorityGridLayout(Rect workArea, int zoneCount, in
|
|||||||
|
|
||||||
bool ZoneSet::CalculateCustomLayout(Rect workArea, int spacing) noexcept
|
bool ZoneSet::CalculateCustomLayout(Rect workArea, int spacing) noexcept
|
||||||
{
|
{
|
||||||
wil::unique_cotaskmem_string guidStr;
|
const auto zoneSetSearchResult = CustomLayouts::instance().GetLayout(m_config.Id);
|
||||||
if (SUCCEEDED(StringFromCLSID(m_config.Id, &guidStr)))
|
if (!zoneSetSearchResult.has_value())
|
||||||
{
|
{
|
||||||
const std::wstring guid = guidStr.get();
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const auto zoneSetSearchResult = FancyZonesDataInstance().FindCustomZoneSet(guid);
|
const auto& zoneSet = *zoneSetSearchResult;
|
||||||
|
if (zoneSet.type == FancyZonesDataTypes::CustomLayoutType::Canvas && std::holds_alternative<FancyZonesDataTypes::CanvasLayoutInfo>(zoneSet.info))
|
||||||
if (!zoneSetSearchResult.has_value())
|
{
|
||||||
|
const auto& zoneSetInfo = std::get<FancyZonesDataTypes::CanvasLayoutInfo>(zoneSet.info);
|
||||||
|
for (const auto& zone : zoneSetInfo.zones)
|
||||||
{
|
{
|
||||||
return false;
|
int x = zone.x;
|
||||||
}
|
int y = zone.y;
|
||||||
|
int width = zone.width;
|
||||||
|
int height = zone.height;
|
||||||
|
|
||||||
const auto& zoneSet = *zoneSetSearchResult;
|
DPIAware::Convert(m_config.Monitor, x, y);
|
||||||
if (zoneSet.type == FancyZonesDataTypes::CustomLayoutType::Canvas && std::holds_alternative<FancyZonesDataTypes::CanvasLayoutInfo>(zoneSet.info))
|
DPIAware::Convert(m_config.Monitor, width, height);
|
||||||
{
|
|
||||||
const auto& zoneSetInfo = std::get<FancyZonesDataTypes::CanvasLayoutInfo>(zoneSet.info);
|
auto zone = MakeZone(RECT{ x, y, x + width, y + height }, m_zones.size());
|
||||||
for (const auto& zone : zoneSetInfo.zones)
|
if (zone)
|
||||||
{
|
{
|
||||||
int x = zone.x;
|
AddZone(zone);
|
||||||
int y = zone.y;
|
|
||||||
int width = zone.width;
|
|
||||||
int height = zone.height;
|
|
||||||
|
|
||||||
DPIAware::Convert(m_config.Monitor, x, y);
|
|
||||||
DPIAware::Convert(m_config.Monitor, width, height);
|
|
||||||
|
|
||||||
auto zone = MakeZone(RECT{ x, y, x + width, y + height }, m_zones.size());
|
|
||||||
if (zone)
|
|
||||||
{
|
|
||||||
AddZone(zone);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// All zones within zone set should be valid in order to use its functionality.
|
|
||||||
m_zones.clear();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// All zones within zone set should be valid in order to use its functionality.
|
||||||
|
m_zones.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (zoneSet.type == FancyZonesDataTypes::CustomLayoutType::Grid && std::holds_alternative<FancyZonesDataTypes::GridLayoutInfo>(zoneSet.info))
|
else if (zoneSet.type == FancyZonesDataTypes::CustomLayoutType::Grid && std::holds_alternative<FancyZonesDataTypes::GridLayoutInfo>(zoneSet.info))
|
||||||
{
|
{
|
||||||
const auto& info = std::get<FancyZonesDataTypes::GridLayoutInfo>(zoneSet.info);
|
const auto& info = std::get<FancyZonesDataTypes::GridLayoutInfo>(zoneSet.info);
|
||||||
return CalculateGridZones(workArea, info, spacing);
|
return CalculateGridZones(workArea, info, spacing);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -3,8 +3,10 @@
|
|||||||
#include "FancyZonesLib/ZoneSet.h"
|
#include "FancyZonesLib/ZoneSet.h"
|
||||||
#include "FancyZonesLib/Settings.h"
|
#include "FancyZonesLib/Settings.h"
|
||||||
#include "FancyZonesLib/FancyZonesData.h"
|
#include "FancyZonesLib/FancyZonesData.h"
|
||||||
|
#include "FancyZonesLib/FancyZonesData/CustomLayouts.h"
|
||||||
#include "FancyZonesLib/FancyZonesData/LayoutHotkeys.h"
|
#include "FancyZonesLib/FancyZonesData/LayoutHotkeys.h"
|
||||||
#include "FancyZonesLib/FancyZonesDataTypes.h"
|
#include "FancyZonesLib/FancyZonesDataTypes.h"
|
||||||
|
#include "FancyZonesLib/util.h"
|
||||||
|
|
||||||
// Telemetry strings should not be localized.
|
// Telemetry strings should not be localized.
|
||||||
#define LoggingProviderKey "Microsoft.PowerToys"
|
#define LoggingProviderKey "Microsoft.PowerToys"
|
||||||
@@ -144,7 +146,7 @@ void Trace::FancyZones::DataChanged() noexcept
|
|||||||
{
|
{
|
||||||
const FancyZonesData& data = FancyZonesDataInstance();
|
const FancyZonesData& data = FancyZonesDataInstance();
|
||||||
int appsHistorySize = static_cast<int>(data.GetAppZoneHistoryMap().size());
|
int appsHistorySize = static_cast<int>(data.GetAppZoneHistoryMap().size());
|
||||||
const auto& customZones = data.GetCustomZoneSetsMap();
|
const auto& customZones = CustomLayouts::instance().GetAllLayouts();
|
||||||
const auto& devices = data.GetDeviceInfoMap();
|
const auto& devices = data.GetDeviceInfoMap();
|
||||||
auto quickKeysCount = LayoutHotkeys::instance().GetHotkeysCount();
|
auto quickKeysCount = LayoutHotkeys::instance().GetHotkeysCount();
|
||||||
|
|
||||||
@@ -190,11 +192,15 @@ void Trace::FancyZones::DataChanged() noexcept
|
|||||||
int zoneCount = -1;
|
int zoneCount = -1;
|
||||||
if (type == FancyZonesDataTypes::ZoneSetLayoutType::Custom)
|
if (type == FancyZonesDataTypes::ZoneSetLayoutType::Custom)
|
||||||
{
|
{
|
||||||
const auto& activeCustomZone = customZones.find(device.activeZoneSet.uuid);
|
auto guid = FancyZonesUtils::GuidFromString(device.activeZoneSet.uuid);
|
||||||
if (activeCustomZone != customZones.end())
|
if (guid)
|
||||||
{
|
{
|
||||||
zoneCount = getCustomZoneCount(activeCustomZone->second.info);
|
const auto& activeCustomZone = customZones.find(guid.value());
|
||||||
}
|
if (activeCustomZone != customZones.end())
|
||||||
|
{
|
||||||
|
zoneCount = getCustomZoneCount(activeCustomZone->second.info);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,194 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
#include <FancyZonesLib/FancyZonesData.h>
|
||||||
|
#include <FancyZonesLib/FancyZonesData/CustomLayouts.h>
|
||||||
|
#include <FancyZonesLib/util.h>
|
||||||
|
|
||||||
|
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||||
|
|
||||||
|
namespace FancyZonesUnitTests
|
||||||
|
{
|
||||||
|
TEST_CLASS (CustomLayoutsUnitTests)
|
||||||
|
{
|
||||||
|
FancyZonesData& m_fzData = FancyZonesDataInstance();
|
||||||
|
std::wstring m_testFolder = L"FancyZonesUnitTests";
|
||||||
|
|
||||||
|
json::JsonObject CanvasLayoutJson()
|
||||||
|
{
|
||||||
|
json::JsonObject canvasLayoutJson{};
|
||||||
|
canvasLayoutJson.SetNamedValue(NonLocalizable::CustomLayoutsIds::UuidID, json::value(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}"));
|
||||||
|
canvasLayoutJson.SetNamedValue(NonLocalizable::CustomLayoutsIds::NameID, json::value(L"Custom canvas layout"));
|
||||||
|
canvasLayoutJson.SetNamedValue(NonLocalizable::CustomLayoutsIds::TypeID, json::value(NonLocalizable::CustomLayoutsIds::CanvasID));
|
||||||
|
|
||||||
|
json::JsonObject info{};
|
||||||
|
info.SetNamedValue(NonLocalizable::CustomLayoutsIds::RefWidthID, json::value(1920));
|
||||||
|
info.SetNamedValue(NonLocalizable::CustomLayoutsIds::RefHeightID, json::value(1080));
|
||||||
|
|
||||||
|
json::JsonArray zonesArray{};
|
||||||
|
{
|
||||||
|
json::JsonObject zone{};
|
||||||
|
zone.SetNamedValue(NonLocalizable::CustomLayoutsIds::XID, json::value(0));
|
||||||
|
zone.SetNamedValue(NonLocalizable::CustomLayoutsIds::YID, json::value(0));
|
||||||
|
zone.SetNamedValue(NonLocalizable::CustomLayoutsIds::WidthID, json::value(1140));
|
||||||
|
zone.SetNamedValue(NonLocalizable::CustomLayoutsIds::HeightID, json::value(1040));
|
||||||
|
zonesArray.Append(zone);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
json::JsonObject zone{};
|
||||||
|
zone.SetNamedValue(NonLocalizable::CustomLayoutsIds::XID, json::value(1140));
|
||||||
|
zone.SetNamedValue(NonLocalizable::CustomLayoutsIds::YID, json::value(649));
|
||||||
|
zone.SetNamedValue(NonLocalizable::CustomLayoutsIds::WidthID, json::value(780));
|
||||||
|
zone.SetNamedValue(NonLocalizable::CustomLayoutsIds::HeightID, json::value(391));
|
||||||
|
zonesArray.Append(zone);
|
||||||
|
}
|
||||||
|
|
||||||
|
info.SetNamedValue(NonLocalizable::CustomLayoutsIds::ZonesID, zonesArray);
|
||||||
|
canvasLayoutJson.SetNamedValue(NonLocalizable::CustomLayoutsIds::InfoID, info);
|
||||||
|
return canvasLayoutJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
json::JsonObject GridLayoutJson()
|
||||||
|
{
|
||||||
|
json::JsonObject gridLayoutJson{};
|
||||||
|
gridLayoutJson.SetNamedValue(NonLocalizable::CustomLayoutsIds::UuidID, json::value(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17D}"));
|
||||||
|
gridLayoutJson.SetNamedValue(NonLocalizable::CustomLayoutsIds::NameID, json::value(L"Custom grid layout"));
|
||||||
|
gridLayoutJson.SetNamedValue(NonLocalizable::CustomLayoutsIds::TypeID, json::value(NonLocalizable::CustomLayoutsIds::GridID));
|
||||||
|
|
||||||
|
json::JsonArray rowsPercentage{};
|
||||||
|
rowsPercentage.Append(json::value(5000));
|
||||||
|
rowsPercentage.Append(json::value(5000));
|
||||||
|
|
||||||
|
json::JsonArray columnsPercentage{};
|
||||||
|
columnsPercentage.Append(json::value(3333));
|
||||||
|
columnsPercentage.Append(json::value(5000));
|
||||||
|
columnsPercentage.Append(json::value(1667));
|
||||||
|
|
||||||
|
json::JsonArray cells{};
|
||||||
|
{
|
||||||
|
json::JsonArray cellsRow{};
|
||||||
|
cellsRow.Append(json::value(0));
|
||||||
|
cellsRow.Append(json::value(1));
|
||||||
|
cellsRow.Append(json::value(2));
|
||||||
|
cells.Append(cellsRow);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
json::JsonArray cellsRow{};
|
||||||
|
cellsRow.Append(json::value(3));
|
||||||
|
cellsRow.Append(json::value(1));
|
||||||
|
cellsRow.Append(json::value(4));
|
||||||
|
cells.Append(cellsRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
json::JsonObject info{};
|
||||||
|
info.SetNamedValue(NonLocalizable::CustomLayoutsIds::RowsID, json::value(2));
|
||||||
|
info.SetNamedValue(NonLocalizable::CustomLayoutsIds::ColumnsID, json::value(3));
|
||||||
|
info.SetNamedValue(NonLocalizable::CustomLayoutsIds::RowsPercentageID, rowsPercentage);
|
||||||
|
info.SetNamedValue(NonLocalizable::CustomLayoutsIds::ColumnsPercentageID, columnsPercentage);
|
||||||
|
info.SetNamedValue(NonLocalizable::CustomLayoutsIds::CellChildMapID, cells);
|
||||||
|
info.SetNamedValue(NonLocalizable::CustomLayoutsIds::SensitivityRadiusID, json::value(20));
|
||||||
|
info.SetNamedValue(NonLocalizable::CustomLayoutsIds::ShowSpacingID, json::value(false));
|
||||||
|
info.SetNamedValue(NonLocalizable::CustomLayoutsIds::SpacingID, json::value(16));
|
||||||
|
|
||||||
|
gridLayoutJson.SetNamedValue(NonLocalizable::CustomLayoutsIds::InfoID, info);
|
||||||
|
return gridLayoutJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD_INITIALIZE(Init)
|
||||||
|
{
|
||||||
|
m_fzData.clear_data();
|
||||||
|
m_fzData.SetSettingsModulePath(L"FancyZonesUnitTests");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD_CLEANUP(CleanUp)
|
||||||
|
{
|
||||||
|
std::filesystem::remove_all(CustomLayouts::CustomLayoutsFileName());
|
||||||
|
std::filesystem::remove_all(PTSettingsHelper::get_module_save_folder_location(m_testFolder));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD (CustomLayoutsParse)
|
||||||
|
{
|
||||||
|
// prepare
|
||||||
|
json::JsonObject root{};
|
||||||
|
json::JsonArray layoutsArray{};
|
||||||
|
|
||||||
|
layoutsArray.Append(CanvasLayoutJson());
|
||||||
|
layoutsArray.Append(GridLayoutJson());
|
||||||
|
|
||||||
|
root.SetNamedValue(NonLocalizable::CustomLayoutsIds::CustomLayoutsArrayID, layoutsArray);
|
||||||
|
json::to_file(CustomLayouts::CustomLayoutsFileName(), root);
|
||||||
|
|
||||||
|
// test
|
||||||
|
CustomLayouts::instance().LoadData();
|
||||||
|
Assert::AreEqual((size_t)2, CustomLayouts::instance().GetAllLayouts().size());
|
||||||
|
Assert::IsTrue(CustomLayouts::instance().GetLayout(FancyZonesUtils::GuidFromString(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}").value()).has_value());
|
||||||
|
Assert::IsTrue(CustomLayouts::instance().GetLayout(FancyZonesUtils::GuidFromString(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17D}").value()).has_value());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD (CustomLayoutsParseEmpty)
|
||||||
|
{
|
||||||
|
// prepare
|
||||||
|
json::JsonObject root{};
|
||||||
|
json::JsonArray layoutsArray{};
|
||||||
|
root.SetNamedValue(NonLocalizable::CustomLayoutsIds::CustomLayoutsArrayID, layoutsArray);
|
||||||
|
json::to_file(CustomLayouts::CustomLayoutsFileName(), root);
|
||||||
|
|
||||||
|
// test
|
||||||
|
CustomLayouts::instance().LoadData();
|
||||||
|
Assert::IsTrue(CustomLayouts::instance().GetAllLayouts().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD (CustomsLayoutsNoFile)
|
||||||
|
{
|
||||||
|
// test
|
||||||
|
CustomLayouts::instance().LoadData();
|
||||||
|
Assert::IsTrue(CustomLayouts::instance().GetAllLayouts().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD (MoveCustomLayoutsFromZonesSettings)
|
||||||
|
{
|
||||||
|
// prepare
|
||||||
|
json::JsonObject root{};
|
||||||
|
json::JsonArray devicesArray{}, customLayoutsArray{}, templateLayoutsArray{}, quickLayoutKeysArray{};
|
||||||
|
customLayoutsArray.Append(GridLayoutJson());
|
||||||
|
customLayoutsArray.Append(CanvasLayoutJson());
|
||||||
|
|
||||||
|
root.SetNamedValue(L"devices", devicesArray);
|
||||||
|
root.SetNamedValue(L"custom-zone-sets", customLayoutsArray);
|
||||||
|
root.SetNamedValue(L"templates", templateLayoutsArray);
|
||||||
|
root.SetNamedValue(L"quick-layout-keys", quickLayoutKeysArray);
|
||||||
|
json::to_file(m_fzData.GetZoneSettingsPath(m_testFolder), root);
|
||||||
|
|
||||||
|
// test
|
||||||
|
m_fzData.ReplaceZoneSettingsFileFromOlderVersions();
|
||||||
|
CustomLayouts::instance().LoadData();
|
||||||
|
Assert::AreEqual((size_t)2, CustomLayouts::instance().GetAllLayouts().size());
|
||||||
|
Assert::IsTrue(CustomLayouts::instance().GetLayout(FancyZonesUtils::GuidFromString(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}").value()).has_value());
|
||||||
|
Assert::IsTrue(CustomLayouts::instance().GetLayout(FancyZonesUtils::GuidFromString(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17D}").value()).has_value());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD (MoveCustomLayoutsFromZonesSettingsNoCustomLayoutsData)
|
||||||
|
{
|
||||||
|
// prepare
|
||||||
|
json::JsonObject root{};
|
||||||
|
json::JsonArray devicesArray{}, templateLayoutsArray{}, quickLayoutKeysArray{};
|
||||||
|
root.SetNamedValue(L"devices", devicesArray);
|
||||||
|
root.SetNamedValue(L"templates", templateLayoutsArray);
|
||||||
|
root.SetNamedValue(L"quick-layout-keys", quickLayoutKeysArray);
|
||||||
|
json::to_file(m_fzData.GetZoneSettingsPath(m_testFolder), root);
|
||||||
|
|
||||||
|
// test
|
||||||
|
m_fzData.ReplaceZoneSettingsFileFromOlderVersions();
|
||||||
|
CustomLayouts::instance().LoadData();
|
||||||
|
Assert::IsTrue(CustomLayouts::instance().GetAllLayouts().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_METHOD (MoveCustomLayoutsFromZonesSettingsNoFile)
|
||||||
|
{
|
||||||
|
// test
|
||||||
|
m_fzData.ReplaceZoneSettingsFileFromOlderVersions();
|
||||||
|
CustomLayouts::instance().LoadData();
|
||||||
|
Assert::IsTrue(CustomLayouts::instance().GetAllLayouts().empty());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -562,7 +562,7 @@ namespace FancyZonesUnitTests
|
|||||||
{
|
{
|
||||||
TEST_METHOD (ToJsonGrid)
|
TEST_METHOD (ToJsonGrid)
|
||||||
{
|
{
|
||||||
CustomZoneSetJSON zoneSet{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Grid, GridLayoutInfo(GridLayoutInfo::Minimal{}) } };
|
CustomZoneSetJSON zoneSet{ L"uuid", CustomLayoutData{ L"name", CustomLayoutType::Grid, GridLayoutInfo(GridLayoutInfo::Minimal{}) } };
|
||||||
|
|
||||||
json::JsonObject expected = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"grid\"}");
|
json::JsonObject expected = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"grid\"}");
|
||||||
expected.SetNamedValue(L"info", GridLayoutInfoJSON::ToJson(std::get<GridLayoutInfo>(zoneSet.data.info)));
|
expected.SetNamedValue(L"info", GridLayoutInfoJSON::ToJson(std::get<GridLayoutInfo>(zoneSet.data.info)));
|
||||||
@@ -574,7 +574,7 @@ namespace FancyZonesUnitTests
|
|||||||
|
|
||||||
TEST_METHOD (ToJsonCanvas)
|
TEST_METHOD (ToJsonCanvas)
|
||||||
{
|
{
|
||||||
CustomZoneSetJSON zoneSet{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{} } };
|
CustomZoneSetJSON zoneSet{ L"uuid", CustomLayoutData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{} } };
|
||||||
|
|
||||||
json::JsonObject expected = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"canvas\"}");
|
json::JsonObject expected = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"canvas\"}");
|
||||||
expected.SetNamedValue(L"info", CanvasLayoutInfoJSON::ToJson(std::get<CanvasLayoutInfo>(zoneSet.data.info)));
|
expected.SetNamedValue(L"info", CanvasLayoutInfoJSON::ToJson(std::get<CanvasLayoutInfo>(zoneSet.data.info)));
|
||||||
@@ -587,7 +587,7 @@ namespace FancyZonesUnitTests
|
|||||||
TEST_METHOD (FromJsonGrid)
|
TEST_METHOD (FromJsonGrid)
|
||||||
{
|
{
|
||||||
const auto grid = GridLayoutInfo(GridLayoutInfo::Full{ 1, 3, { 10000 }, { 2500, 5000, 2500 }, { { 0, 1, 2 } } });
|
const auto grid = GridLayoutInfo(GridLayoutInfo::Full{ 1, 3, { 10000 }, { 2500, 5000, 2500 }, { { 0, 1, 2 } } });
|
||||||
CustomZoneSetJSON expected{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } };
|
CustomZoneSetJSON expected{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", CustomLayoutData{ L"name", CustomLayoutType::Grid, grid } };
|
||||||
|
|
||||||
json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\", \"name\": \"name\", \"type\": \"grid\"}");
|
json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\", \"name\": \"name\", \"type\": \"grid\"}");
|
||||||
json.SetNamedValue(L"info", GridLayoutInfoJSON::ToJson(std::get<GridLayoutInfo>(expected.data.info)));
|
json.SetNamedValue(L"info", GridLayoutInfoJSON::ToJson(std::get<GridLayoutInfo>(expected.data.info)));
|
||||||
@@ -607,7 +607,7 @@ namespace FancyZonesUnitTests
|
|||||||
|
|
||||||
TEST_METHOD (FromJsonCanvas)
|
TEST_METHOD (FromJsonCanvas)
|
||||||
{
|
{
|
||||||
CustomZoneSetJSON expected{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 2, 1 } } };
|
CustomZoneSetJSON expected{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", CustomLayoutData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 2, 1 } } };
|
||||||
|
|
||||||
json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\", \"name\": \"name\", \"type\": \"canvas\"}");
|
json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"{33A2B101-06E0-437B-A61E-CDBECF502906}\", \"name\": \"name\", \"type\": \"canvas\"}");
|
||||||
json.SetNamedValue(L"info", CanvasLayoutInfoJSON::ToJson(std::get<CanvasLayoutInfo>(expected.data.info)));
|
json.SetNamedValue(L"info", CanvasLayoutInfoJSON::ToJson(std::get<CanvasLayoutInfo>(expected.data.info)));
|
||||||
@@ -628,7 +628,7 @@ namespace FancyZonesUnitTests
|
|||||||
TEST_METHOD (FromJsonGridInvalidUuid)
|
TEST_METHOD (FromJsonGridInvalidUuid)
|
||||||
{
|
{
|
||||||
const auto grid = GridLayoutInfo(GridLayoutInfo::Full{ 1, 3, { 10000 }, { 2500, 5000, 2500 }, { { 0, 1, 2 } } });
|
const auto grid = GridLayoutInfo(GridLayoutInfo::Full{ 1, 3, { 10000 }, { 2500, 5000, 2500 }, { { 0, 1, 2 } } });
|
||||||
CustomZoneSetJSON expected{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } };
|
CustomZoneSetJSON expected{ L"uuid", CustomLayoutData{ L"name", CustomLayoutType::Grid, grid } };
|
||||||
|
|
||||||
json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"grid\"}");
|
json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"grid\"}");
|
||||||
json.SetNamedValue(L"info", GridLayoutInfoJSON::ToJson(std::get<GridLayoutInfo>(expected.data.info)));
|
json.SetNamedValue(L"info", GridLayoutInfoJSON::ToJson(std::get<GridLayoutInfo>(expected.data.info)));
|
||||||
@@ -639,7 +639,7 @@ namespace FancyZonesUnitTests
|
|||||||
|
|
||||||
TEST_METHOD (FromJsonCanvasInvalidUuid)
|
TEST_METHOD (FromJsonCanvasInvalidUuid)
|
||||||
{
|
{
|
||||||
CustomZoneSetJSON expected{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 2, 1 } } };
|
CustomZoneSetJSON expected{ L"uuid", CustomLayoutData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 2, 1 } } };
|
||||||
|
|
||||||
json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"canvas\"}");
|
json::JsonObject json = json::JsonObject::Parse(L"{\"uuid\": \"uuid\", \"name\": \"name\", \"type\": \"canvas\"}");
|
||||||
json.SetNamedValue(L"info", CanvasLayoutInfoJSON::ToJson(std::get<CanvasLayoutInfo>(expected.data.info)));
|
json.SetNamedValue(L"info", CanvasLayoutInfoJSON::ToJson(std::get<CanvasLayoutInfo>(expected.data.info)));
|
||||||
@@ -650,7 +650,7 @@ namespace FancyZonesUnitTests
|
|||||||
|
|
||||||
TEST_METHOD (FromJsonMissingKeys)
|
TEST_METHOD (FromJsonMissingKeys)
|
||||||
{
|
{
|
||||||
CustomZoneSetJSON zoneSet{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 2, 1 } } };
|
CustomZoneSetJSON zoneSet{ L"uuid", CustomLayoutData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 2, 1 } } };
|
||||||
const auto json = CustomZoneSetJSON::ToJson(zoneSet);
|
const auto json = CustomZoneSetJSON::ToJson(zoneSet);
|
||||||
|
|
||||||
auto iter = json.First();
|
auto iter = json.First();
|
||||||
@@ -1371,158 +1371,6 @@ namespace FancyZonesUnitTests
|
|||||||
auto res = CustomAssert::CompareJsonArrays(expected, actual);
|
auto res = CustomAssert::CompareJsonArrays(expected, actual);
|
||||||
Assert::IsTrue(res.first, res.second.c_str());
|
Assert::IsTrue(res.first, res.second.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_METHOD (CustomZoneSetsParseSingle)
|
|
||||||
{
|
|
||||||
const std::wstring zoneUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}";
|
|
||||||
GridLayoutInfo grid(GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{
|
|
||||||
.rows = 1,
|
|
||||||
.columns = 3,
|
|
||||||
.rowsPercents = { 10000 },
|
|
||||||
.columnsPercents = { 2500, 5000, 2500 },
|
|
||||||
.cellChildMap = { { 0, 1, 2 } } }));
|
|
||||||
|
|
||||||
json::JsonObject json;
|
|
||||||
CustomZoneSetJSON expected{ zoneUuid, CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } };
|
|
||||||
json::JsonArray array;
|
|
||||||
array.Append(CustomZoneSetJSON::ToJson(expected));
|
|
||||||
json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(array.Stringify()));
|
|
||||||
|
|
||||||
const auto& customZoneSetsMap = ParseCustomZoneSets(json);
|
|
||||||
|
|
||||||
Assert::AreEqual((size_t)array.Size(), customZoneSetsMap.size());
|
|
||||||
|
|
||||||
auto entry = customZoneSetsMap.find(zoneUuid)->second;
|
|
||||||
Assert::AreEqual(expected.data.name.c_str(), entry.name.c_str());
|
|
||||||
Assert::AreEqual((int)expected.data.type, (int)entry.type);
|
|
||||||
|
|
||||||
auto expectedGrid = std::get<GridLayoutInfo>(expected.data.info);
|
|
||||||
auto actualGrid = std::get<GridLayoutInfo>(entry.info);
|
|
||||||
Assert::AreEqual(expectedGrid.rows(), actualGrid.rows());
|
|
||||||
Assert::AreEqual(expectedGrid.columns(), actualGrid.columns());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_METHOD (CustomZoneSetsParseMany)
|
|
||||||
{
|
|
||||||
json::JsonObject json;
|
|
||||||
json::JsonArray array;
|
|
||||||
const GridLayoutInfo grid(GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{
|
|
||||||
.rows = 1,
|
|
||||||
.columns = 3,
|
|
||||||
.rowsPercents = { 10000 },
|
|
||||||
.columnsPercents = { 2500, 5000, 2500 },
|
|
||||||
.cellChildMap = { { 0, 1, 2 } } }));
|
|
||||||
array.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502900}", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } }));
|
|
||||||
array.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502901}", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 1, 2 } } }));
|
|
||||||
array.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502902}", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } }));
|
|
||||||
array.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502903}", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 1, 2 } } }));
|
|
||||||
json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(array.Stringify()));
|
|
||||||
|
|
||||||
const auto& customZoneSetsMap = ParseCustomZoneSets(json);
|
|
||||||
|
|
||||||
Assert::AreEqual((size_t)array.Size(), customZoneSetsMap.size());
|
|
||||||
|
|
||||||
auto iter = array.First();
|
|
||||||
while (iter.HasCurrent())
|
|
||||||
{
|
|
||||||
auto expected = CustomZoneSetJSON::FromJson(json::JsonObject::Parse(iter.Current().Stringify()));
|
|
||||||
auto entry = customZoneSetsMap.find(expected->uuid)->second;
|
|
||||||
Assert::AreEqual(expected->data.name.c_str(), entry.name.c_str(), L"name");
|
|
||||||
Assert::AreEqual((int)expected->data.type, (int)entry.type, L"type");
|
|
||||||
|
|
||||||
if (expected->data.type == CustomLayoutType::Grid)
|
|
||||||
{
|
|
||||||
auto expectedInfo = std::get<GridLayoutInfo>(expected->data.info);
|
|
||||||
auto actualInfo = std::get<GridLayoutInfo>(entry.info);
|
|
||||||
Assert::AreEqual(expectedInfo.rows(), actualInfo.rows(), L"grid rows");
|
|
||||||
Assert::AreEqual(expectedInfo.columns(), actualInfo.columns(), L"grid columns");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto expectedInfo = std::get<CanvasLayoutInfo>(expected->data.info);
|
|
||||||
auto actualInfo = std::get<CanvasLayoutInfo>(entry.info);
|
|
||||||
Assert::AreEqual(expectedInfo.lastWorkAreaWidth, actualInfo.lastWorkAreaWidth, L"canvas width");
|
|
||||||
Assert::AreEqual(expectedInfo.lastWorkAreaHeight, actualInfo.lastWorkAreaHeight, L"canvas height");
|
|
||||||
}
|
|
||||||
|
|
||||||
iter.MoveNext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_METHOD (CustomZoneSetsParseEmpty)
|
|
||||||
{
|
|
||||||
const auto& customZoneSetsMap = ParseCustomZoneSets(json::JsonObject());
|
|
||||||
|
|
||||||
Assert::IsTrue(customZoneSetsMap.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_METHOD (CustomZoneSetsParseInvalid)
|
|
||||||
{
|
|
||||||
json::JsonObject json;
|
|
||||||
CustomZoneSetJSON expected{ L"uuid", CustomZoneSetData{ L"name", CustomLayoutType::Grid, GridLayoutInfo(GridLayoutInfo::Minimal{ 1, 2 }) } };
|
|
||||||
json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(CustomZoneSetJSON::ToJson(expected).Stringify()));
|
|
||||||
|
|
||||||
const auto& customZoneSetsMap = ParseCustomZoneSets(json);
|
|
||||||
|
|
||||||
Assert::IsTrue(customZoneSetsMap.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_METHOD (CustomZoneSetsSerializeSingle)
|
|
||||||
{
|
|
||||||
json::JsonArray expected;
|
|
||||||
const GridLayoutInfo grid(GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{
|
|
||||||
.rows = 1,
|
|
||||||
.columns = 3,
|
|
||||||
.rowsPercents = { 10000 },
|
|
||||||
.columnsPercents = { 2500, 5000, 2500 },
|
|
||||||
.cellChildMap = { { 0, 1, 2 } } }));
|
|
||||||
expected.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } }));
|
|
||||||
json::JsonObject json;
|
|
||||||
json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(expected.Stringify()));
|
|
||||||
|
|
||||||
const auto& customZoneSetsMap = ParseCustomZoneSets(json);
|
|
||||||
|
|
||||||
auto actual = SerializeCustomZoneSets(customZoneSetsMap);
|
|
||||||
auto res = CustomAssert::CompareJsonArrays(expected, actual);
|
|
||||||
Assert::IsTrue(res.first, res.second.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_METHOD (CustomZoneSetsSerializeMany)
|
|
||||||
{
|
|
||||||
json::JsonObject json;
|
|
||||||
json::JsonArray expected;
|
|
||||||
const GridLayoutInfo grid(GridLayoutInfo(FancyZonesDataTypes::GridLayoutInfo::Full{
|
|
||||||
.rows = 1,
|
|
||||||
.columns = 3,
|
|
||||||
.rowsPercents = { 10000 },
|
|
||||||
.columnsPercents = { 2500, 5000, 2500 },
|
|
||||||
.cellChildMap = { { 0, 1, 2 } } }));
|
|
||||||
|
|
||||||
expected.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502900}", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } }));
|
|
||||||
expected.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502901}", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 1, 2 } } }));
|
|
||||||
expected.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502902}", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } }));
|
|
||||||
expected.Append(CustomZoneSetJSON::ToJson(CustomZoneSetJSON{ L"{33A2B101-06E0-437B-A61E-CDBECF502903}", CustomZoneSetData{ L"name", CustomLayoutType::Canvas, CanvasLayoutInfo{ 1, 2 } } }));
|
|
||||||
json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(expected.Stringify()));
|
|
||||||
|
|
||||||
const auto& customZoneSetsMap = ParseCustomZoneSets(json);
|
|
||||||
|
|
||||||
auto actual = SerializeCustomZoneSets(customZoneSetsMap);
|
|
||||||
auto res = CustomAssert::CompareJsonArrays(expected, actual);
|
|
||||||
Assert::IsTrue(res.first, res.second.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_METHOD (CustomZoneSetsSerializeEmpty)
|
|
||||||
{
|
|
||||||
json::JsonArray expected;
|
|
||||||
json::JsonObject json;
|
|
||||||
json.SetNamedValue(L"custom-zone-sets", json::JsonValue::Parse(expected.Stringify()));
|
|
||||||
|
|
||||||
const auto& customZoneSetsMap = ParseCustomZoneSets(json);
|
|
||||||
|
|
||||||
auto actual = SerializeCustomZoneSets(customZoneSetsMap);
|
|
||||||
auto res = CustomAssert::CompareJsonArrays(expected, actual);
|
|
||||||
Assert::IsTrue(res.first, res.second.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_METHOD (SetActiveZoneSet)
|
TEST_METHOD (SetActiveZoneSet)
|
||||||
{
|
{
|
||||||
@@ -1620,13 +1468,13 @@ namespace FancyZonesUnitTests
|
|||||||
.rowsPercents = { 10000 },
|
.rowsPercents = { 10000 },
|
||||||
.columnsPercents = { 2500, 5000, 2500 },
|
.columnsPercents = { 2500, 5000, 2500 },
|
||||||
.cellChildMap = { { 0, 1, 2 } } }));
|
.cellChildMap = { { 0, 1, 2 } } }));
|
||||||
CustomZoneSetJSON zoneSets{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } };
|
CustomZoneSetJSON zoneSets{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", CustomLayoutData{ L"name", CustomLayoutType::Grid, grid } };
|
||||||
AppZoneHistoryData data{
|
AppZoneHistoryData data{
|
||||||
.zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = L"device-id", .zoneIndexSet = { 54321 }
|
.zoneSetUuid = L"{33A2B101-06E0-437B-A61E-CDBECF502906}", .deviceId = L"device-id", .zoneIndexSet = { 54321 }
|
||||||
};
|
};
|
||||||
AppZoneHistoryJSON appZoneHistory{ L"app-path", std::vector<AppZoneHistoryData>{ data } };
|
AppZoneHistoryJSON appZoneHistory{ L"app-path", std::vector<AppZoneHistoryData>{ data } };
|
||||||
|
|
||||||
DeviceInfoJSON deviceInfo { FancyZonesDataTypes::DeviceIdData{ L"device-id", 0, 0, m_defaultVDId }, DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 } };
|
DeviceInfoJSON deviceInfo { FancyZonesDataTypes::DeviceIdData{ L"device-id", 0, 0, m_defaultVDId }, DeviceInfoData{ ZoneSetData{ L"{33A2B101-16E1-437B-A61E-CDBECF502906}", ZoneSetLayoutType::Custom }, true, 16, 3 } };
|
||||||
LayoutQuickKeyJSON quickKeys{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", 1 };
|
LayoutQuickKeyJSON quickKeys{ L"{33A2B101-06E0-437B-A61E-CDBECF502906}", 1 };
|
||||||
json::JsonArray zoneSetsArray, appZonesArray, deviceInfoArray, quickKeysArray;
|
json::JsonArray zoneSetsArray, appZonesArray, deviceInfoArray, quickKeysArray;
|
||||||
zoneSetsArray.Append(CustomZoneSetJSON::ToJson(zoneSets));
|
zoneSetsArray.Append(CustomZoneSetJSON::ToJson(zoneSets));
|
||||||
@@ -1651,9 +1499,8 @@ namespace FancyZonesUnitTests
|
|||||||
std::filesystem::remove(jsonPath);
|
std::filesystem::remove(jsonPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert::IsFalse(fancyZonesData.GetCustomZoneSetsMap().empty());
|
Assert::IsFalse(fancyZonesData.GetAppZoneHistoryMap().empty());
|
||||||
Assert::IsFalse(fancyZonesData.GetCustomZoneSetsMap().empty());
|
Assert::IsFalse(fancyZonesData.GetDeviceInfoMap().empty());
|
||||||
Assert::IsFalse(fancyZonesData.GetCustomZoneSetsMap().empty());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_METHOD (LoadFancyZonesDataFromCroppedJson)
|
TEST_METHOD (LoadFancyZonesDataFromCroppedJson)
|
||||||
@@ -1666,7 +1513,6 @@ namespace FancyZonesUnitTests
|
|||||||
|
|
||||||
data.LoadFancyZonesData();
|
data.LoadFancyZonesData();
|
||||||
|
|
||||||
Assert::IsTrue(data.GetCustomZoneSetsMap().empty());
|
|
||||||
Assert::IsTrue(data.GetAppZoneHistoryMap().empty());
|
Assert::IsTrue(data.GetAppZoneHistoryMap().empty());
|
||||||
Assert::IsTrue(data.GetDeviceInfoMap().empty());
|
Assert::IsTrue(data.GetDeviceInfoMap().empty());
|
||||||
}
|
}
|
||||||
@@ -1680,7 +1526,6 @@ namespace FancyZonesUnitTests
|
|||||||
std::wofstream{ jsonPath.data(), std::ios::binary } << L"{ \"app-zone-history\": [], \"devices\": [{\"device-id\": \"кириллица\"}], \"custom-zone-sets\": []}";
|
std::wofstream{ jsonPath.data(), std::ios::binary } << L"{ \"app-zone-history\": [], \"devices\": [{\"device-id\": \"кириллица\"}], \"custom-zone-sets\": []}";
|
||||||
data.LoadFancyZonesData();
|
data.LoadFancyZonesData();
|
||||||
|
|
||||||
Assert::IsTrue(data.GetCustomZoneSetsMap().empty());
|
|
||||||
Assert::IsTrue(data.GetAppZoneHistoryMap().empty());
|
Assert::IsTrue(data.GetAppZoneHistoryMap().empty());
|
||||||
Assert::IsTrue(data.GetDeviceInfoMap().empty());
|
Assert::IsTrue(data.GetDeviceInfoMap().empty());
|
||||||
}
|
}
|
||||||
@@ -1694,7 +1539,6 @@ namespace FancyZonesUnitTests
|
|||||||
std::wofstream{ jsonPath.data(), std::ios::binary } << L"{ \"app-zone-history\": null, \"devices\": [{\"device-id\":\"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\",\"active-zoneset\":{\"uuid\":\"{568EBC3A-C09C-483E-A64D-6F1F2AF4E48D}\",\"type\":\"columns\"},\"editor-show-spacing\":true,\"editor-spacing\":16,\"editor-zone-count\":3}], \"custom-zone-sets\": []}";
|
std::wofstream{ jsonPath.data(), std::ios::binary } << L"{ \"app-zone-history\": null, \"devices\": [{\"device-id\":\"AOC2460#4&fe3a015&0&UID65793_1920_1200_{39B25DD2-130D-4B5D-8851-4791D66B1539}\",\"active-zoneset\":{\"uuid\":\"{568EBC3A-C09C-483E-A64D-6F1F2AF4E48D}\",\"type\":\"columns\"},\"editor-show-spacing\":true,\"editor-spacing\":16,\"editor-zone-count\":3}], \"custom-zone-sets\": []}";
|
||||||
data.LoadFancyZonesData();
|
data.LoadFancyZonesData();
|
||||||
|
|
||||||
Assert::IsTrue(data.GetCustomZoneSetsMap().empty());
|
|
||||||
Assert::IsTrue(data.GetAppZoneHistoryMap().empty());
|
Assert::IsTrue(data.GetAppZoneHistoryMap().empty());
|
||||||
Assert::IsFalse(data.GetDeviceInfoMap().empty());
|
Assert::IsFalse(data.GetDeviceInfoMap().empty());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="CustomLayoutsTests.Spec.cpp" />
|
||||||
<ClCompile Include="FancyZones.Spec.cpp" />
|
<ClCompile Include="FancyZones.Spec.cpp" />
|
||||||
<ClCompile Include="FancyZonesSettings.Spec.cpp" />
|
<ClCompile Include="FancyZonesSettings.Spec.cpp" />
|
||||||
<ClCompile Include="JsonHelpers.Tests.cpp" />
|
<ClCompile Include="JsonHelpers.Tests.cpp" />
|
||||||
|
|||||||
@@ -48,6 +48,9 @@
|
|||||||
<ClCompile Include="LayoutTemplatesTests.Spec.cpp">
|
<ClCompile Include="LayoutTemplatesTests.Spec.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="CustomLayoutsTests.Spec.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="pch.h">
|
<ClInclude Include="pch.h">
|
||||||
|
|||||||
@@ -1000,7 +1000,7 @@ namespace FancyZonesUnitTests
|
|||||||
{
|
{
|
||||||
const std::wstring uuid = L"uuid";
|
const std::wstring uuid = L"uuid";
|
||||||
const CanvasLayoutInfo info{ -1, 100, { CanvasLayoutInfo::Rect{ -10, -10, 100, 100 }, CanvasLayoutInfo::Rect{ 50, 50, 150, 150 } } };
|
const CanvasLayoutInfo info{ -1, 100, { CanvasLayoutInfo::Rect{ -10, -10, 100, 100 }, CanvasLayoutInfo::Rect{ 50, 50, 150, 150 } } };
|
||||||
JSONHelpers::CustomZoneSetJSON expected{ uuid, CustomZoneSetData{ L"name", CustomLayoutType::Canvas, info } };
|
JSONHelpers::CustomZoneSetJSON expected{ uuid, CustomLayoutData{ L"name", CustomLayoutType::Canvas, info } };
|
||||||
json::to_file(m_path, JSONHelpers::CustomZoneSetJSON::ToJson(expected));
|
json::to_file(m_path, JSONHelpers::CustomZoneSetJSON::ToJson(expected));
|
||||||
Assert::IsTrue(std::filesystem::exists(m_path));
|
Assert::IsTrue(std::filesystem::exists(m_path));
|
||||||
|
|
||||||
@@ -1026,7 +1026,7 @@ namespace FancyZonesUnitTests
|
|||||||
.rowsPercents = { -100 }, //rows percents are negative
|
.rowsPercents = { -100 }, //rows percents are negative
|
||||||
.columnsPercents = { 2500, 2500 }, //column percents count is invalid
|
.columnsPercents = { 2500, 2500 }, //column percents count is invalid
|
||||||
.cellChildMap = { { 0, 1, 2 } } }));
|
.cellChildMap = { { 0, 1, 2 } } }));
|
||||||
JSONHelpers::CustomZoneSetJSON expected{ uuid, CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } };
|
JSONHelpers::CustomZoneSetJSON expected{ uuid, CustomLayoutData{ L"name", CustomLayoutType::Grid, grid } };
|
||||||
json::to_file(m_path, JSONHelpers::CustomZoneSetJSON::ToJson(expected));
|
json::to_file(m_path, JSONHelpers::CustomZoneSetJSON::ToJson(expected));
|
||||||
Assert::IsTrue(std::filesystem::exists(m_path));
|
Assert::IsTrue(std::filesystem::exists(m_path));
|
||||||
|
|
||||||
@@ -1043,69 +1043,13 @@ namespace FancyZonesUnitTests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_METHOD (CustomZoneFromValidCanvasLayoutInfo)
|
|
||||||
{
|
|
||||||
//prepare device data
|
|
||||||
FancyZonesDataInstance().SetDeviceInfo(FancyZonesDataTypes::DeviceIdData{ L"default_device_id" }, DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 });
|
|
||||||
|
|
||||||
//prepare expected data
|
|
||||||
wil::unique_cotaskmem_string uuid;
|
|
||||||
Assert::AreEqual(S_OK, StringFromCLSID(m_id, &uuid));
|
|
||||||
const CanvasLayoutInfo info{ 123, 321, { CanvasLayoutInfo::Rect{ 0, 0, 100, 100 }, CanvasLayoutInfo::Rect{ 50, 50, 150, 150 } } };
|
|
||||||
CustomZoneSetData zoneSetData{ L"name", CustomLayoutType::Canvas, info };
|
|
||||||
FancyZonesDataInstance().SetCustomZonesets(uuid.get(), zoneSetData);
|
|
||||||
|
|
||||||
//test
|
|
||||||
const int spacing = 10;
|
|
||||||
const int zoneCount = static_cast<int>(info.zones.size());
|
|
||||||
ZoneSetConfig m_config = ZoneSetConfig(m_id, ZoneSetLayoutType::Custom, m_monitor, DefaultValues::SensitivityRadius);
|
|
||||||
for (const auto& monitorInfo : m_popularMonitors)
|
|
||||||
{
|
|
||||||
auto set = MakeZoneSet(m_config);
|
|
||||||
auto result = set->CalculateZones(monitorInfo.rcWork, zoneCount, spacing);
|
|
||||||
Assert::IsTrue(result);
|
|
||||||
checkZones(set, ZoneSetLayoutType::Custom, zoneCount, monitorInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_METHOD (CustomZoneFromValidGridFullLayoutInfo)
|
|
||||||
{
|
|
||||||
//prepare device data
|
|
||||||
FancyZonesDataInstance().SetDeviceInfo(FancyZonesDataTypes::DeviceIdData{ L"default_device_id" }, DeviceInfoData{ ZoneSetData{ L"uuid", ZoneSetLayoutType::Custom }, true, 16, 3 });
|
|
||||||
|
|
||||||
//prepare expected data
|
|
||||||
wil::unique_cotaskmem_string uuid;
|
|
||||||
Assert::AreEqual(S_OK, StringFromCLSID(m_id, &uuid));
|
|
||||||
const GridLayoutInfo grid(GridLayoutInfo(GridLayoutInfo::Full{
|
|
||||||
.rows = 1,
|
|
||||||
.columns = 3,
|
|
||||||
.rowsPercents = { 10000 },
|
|
||||||
.columnsPercents = { 2500, 5000, 2500 },
|
|
||||||
.cellChildMap = { { 0, 1, 2 } } }));
|
|
||||||
CustomZoneSetData zoneSetData{ L"name", CustomLayoutType::Grid, grid };
|
|
||||||
FancyZonesDataInstance().SetCustomZonesets(uuid.get(), zoneSetData);
|
|
||||||
|
|
||||||
const int spacing = 10;
|
|
||||||
const int zoneCount = grid.rows() * grid.columns();
|
|
||||||
|
|
||||||
ZoneSetConfig m_config = ZoneSetConfig(m_id, ZoneSetLayoutType::Custom, m_monitor, DefaultValues::SensitivityRadius);
|
|
||||||
|
|
||||||
for (const auto& monitorInfo : m_popularMonitors)
|
|
||||||
{
|
|
||||||
auto set = MakeZoneSet(m_config);
|
|
||||||
auto result = set->CalculateZones(monitorInfo.rcWork, zoneCount, spacing);
|
|
||||||
Assert::IsTrue(result);
|
|
||||||
checkZones(set, ZoneSetLayoutType::Custom, zoneCount, monitorInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_METHOD (CustomZoneFromValidGridMinimalLayoutInfo)
|
TEST_METHOD (CustomZoneFromValidGridMinimalLayoutInfo)
|
||||||
{
|
{
|
||||||
const std::wstring uuid = L"uuid";
|
const std::wstring uuid = L"uuid";
|
||||||
const GridLayoutInfo grid(GridLayoutInfo(GridLayoutInfo::Minimal{
|
const GridLayoutInfo grid(GridLayoutInfo(GridLayoutInfo::Minimal{
|
||||||
.rows = 1,
|
.rows = 1,
|
||||||
.columns = 3 }));
|
.columns = 3 }));
|
||||||
JSONHelpers::CustomZoneSetJSON expected{ uuid, CustomZoneSetData{ L"name", CustomLayoutType::Grid, grid } };
|
JSONHelpers::CustomZoneSetJSON expected{ uuid, CustomLayoutData{ L"name", CustomLayoutType::Grid, grid } };
|
||||||
json::to_file(m_path, JSONHelpers::CustomZoneSetJSON::ToJson(expected));
|
json::to_file(m_path, JSONHelpers::CustomZoneSetJSON::ToJson(expected));
|
||||||
Assert::IsTrue(std::filesystem::exists(m_path));
|
Assert::IsTrue(std::filesystem::exists(m_path));
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ namespace FancyZonesEditor
|
|||||||
}
|
}
|
||||||
|
|
||||||
App.FancyZonesEditorIO.SerializeLayoutTemplates();
|
App.FancyZonesEditorIO.SerializeLayoutTemplates();
|
||||||
|
App.FancyZonesEditorIO.SerializeCustomLayouts();
|
||||||
|
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -251,6 +251,7 @@ namespace FancyZonesEditor
|
|||||||
|
|
||||||
App.Overlay.SetLayoutSettings(App.Overlay.Monitors[App.Overlay.CurrentDesktop], model);
|
App.Overlay.SetLayoutSettings(App.Overlay.Monitors[App.Overlay.CurrentDesktop], model);
|
||||||
App.FancyZonesEditorIO.SerializeZoneSettings();
|
App.FancyZonesEditorIO.SerializeZoneSettings();
|
||||||
|
App.FancyZonesEditorIO.SerializeCustomLayouts();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Announce(string name, string message)
|
private void Announce(string name, string message)
|
||||||
@@ -272,6 +273,7 @@ namespace FancyZonesEditor
|
|||||||
_settings.SetAppliedModel(model);
|
_settings.SetAppliedModel(model);
|
||||||
App.Overlay.SetLayoutSettings(App.Overlay.Monitors[App.Overlay.CurrentDesktop], model);
|
App.Overlay.SetLayoutSettings(App.Overlay.Monitors[App.Overlay.CurrentDesktop], model);
|
||||||
App.FancyZonesEditorIO.SerializeZoneSettings();
|
App.FancyZonesEditorIO.SerializeZoneSettings();
|
||||||
|
App.FancyZonesEditorIO.SerializeCustomLayouts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,6 +283,7 @@ namespace FancyZonesEditor
|
|||||||
CancelLayoutChanges();
|
CancelLayoutChanges();
|
||||||
|
|
||||||
App.FancyZonesEditorIO.SerializeZoneSettings();
|
App.FancyZonesEditorIO.SerializeZoneSettings();
|
||||||
|
App.FancyZonesEditorIO.SerializeCustomLayouts();
|
||||||
App.FancyZonesEditorIO.SerializeLayoutHotkeys();
|
App.FancyZonesEditorIO.SerializeLayoutHotkeys();
|
||||||
App.FancyZonesEditorIO.SerializeLayoutTemplates();
|
App.FancyZonesEditorIO.SerializeLayoutTemplates();
|
||||||
App.Overlay.CloseLayoutWindow();
|
App.Overlay.CloseLayoutWindow();
|
||||||
@@ -426,6 +429,7 @@ namespace FancyZonesEditor
|
|||||||
}
|
}
|
||||||
|
|
||||||
App.FancyZonesEditorIO.SerializeZoneSettings();
|
App.FancyZonesEditorIO.SerializeZoneSettings();
|
||||||
|
App.FancyZonesEditorIO.SerializeCustomLayouts();
|
||||||
App.FancyZonesEditorIO.SerializeLayoutTemplates();
|
App.FancyZonesEditorIO.SerializeLayoutTemplates();
|
||||||
App.FancyZonesEditorIO.SerializeLayoutHotkeys();
|
App.FancyZonesEditorIO.SerializeLayoutHotkeys();
|
||||||
|
|
||||||
@@ -472,6 +476,7 @@ namespace FancyZonesEditor
|
|||||||
}
|
}
|
||||||
|
|
||||||
App.FancyZonesEditorIO.SerializeZoneSettings();
|
App.FancyZonesEditorIO.SerializeZoneSettings();
|
||||||
|
App.FancyZonesEditorIO.SerializeCustomLayouts();
|
||||||
model.Delete();
|
model.Delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -375,6 +375,15 @@ namespace FancyZonesEditor.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to An error occurred while parsing custom layouts..
|
||||||
|
/// </summary>
|
||||||
|
public static string Error_Parsing_Custom_Layouts_Message {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Error_Parsing_Custom_Layouts_Message", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Error parsing device info data..
|
/// Looks up a localized string similar to Error parsing device info data..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
@@ -389,4 +389,7 @@
|
|||||||
<data name="Error_Parsing_Layout_Templates_Message" xml:space="preserve">
|
<data name="Error_Parsing_Layout_Templates_Message" xml:space="preserve">
|
||||||
<value>An error occurred while parsing template layouts.</value>
|
<value>An error occurred while parsing template layouts.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Error_Parsing_Custom_Layouts_Message" xml:space="preserve">
|
||||||
|
<value>An error occurred while parsing custom layouts.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -31,6 +31,7 @@ namespace FancyZonesEditor.Utils
|
|||||||
private const string ZonesSettingsFile = "\\Microsoft\\PowerToys\\FancyZones\\zones-settings.json";
|
private const string ZonesSettingsFile = "\\Microsoft\\PowerToys\\FancyZones\\zones-settings.json";
|
||||||
private const string LayoutHotkeysFile = "\\Microsoft\\PowerToys\\FancyZones\\layout-hotkeys.json";
|
private const string LayoutHotkeysFile = "\\Microsoft\\PowerToys\\FancyZones\\layout-hotkeys.json";
|
||||||
private const string LayoutTemplatesFile = "\\Microsoft\\PowerToys\\FancyZones\\layout-templates.json";
|
private const string LayoutTemplatesFile = "\\Microsoft\\PowerToys\\FancyZones\\layout-templates.json";
|
||||||
|
private const string CustomLayoutsFile = "\\Microsoft\\PowerToys\\FancyZones\\custom-layouts.json";
|
||||||
private const string ParamsFile = "\\Microsoft\\PowerToys\\FancyZones\\editor-parameters.json";
|
private const string ParamsFile = "\\Microsoft\\PowerToys\\FancyZones\\editor-parameters.json";
|
||||||
|
|
||||||
// Non-localizable string: Multi-monitor id
|
// Non-localizable string: Multi-monitor id
|
||||||
@@ -55,6 +56,8 @@ namespace FancyZonesEditor.Utils
|
|||||||
|
|
||||||
public string FancyZonesLayoutTemplatesFile { get; private set; }
|
public string FancyZonesLayoutTemplatesFile { get; private set; }
|
||||||
|
|
||||||
|
public string FancyZonesCustomLayoutsFile { get; private set; }
|
||||||
|
|
||||||
public string FancyZonesEditorParamsFile { get; private set; }
|
public string FancyZonesEditorParamsFile { get; private set; }
|
||||||
|
|
||||||
private enum CmdArgs
|
private enum CmdArgs
|
||||||
@@ -130,7 +133,7 @@ namespace FancyZonesEditor.Utils
|
|||||||
public int EditorSensitivityRadius { get; set; }
|
public int EditorSensitivityRadius { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// zones-settings: custom-zone-sets
|
// custom-layouts.json
|
||||||
private class CanvasInfoWrapper
|
private class CanvasInfoWrapper
|
||||||
{
|
{
|
||||||
public struct CanvasZoneWrapper
|
public struct CanvasZoneWrapper
|
||||||
@@ -153,7 +156,7 @@ namespace FancyZonesEditor.Utils
|
|||||||
public int SensitivityRadius { get; set; } = LayoutSettings.DefaultSensitivityRadius;
|
public int SensitivityRadius { get; set; } = LayoutSettings.DefaultSensitivityRadius;
|
||||||
}
|
}
|
||||||
|
|
||||||
// zones-settings: custom-zone-sets
|
// custom-layouts.json
|
||||||
private class GridInfoWrapper
|
private class GridInfoWrapper
|
||||||
{
|
{
|
||||||
public int Rows { get; set; }
|
public int Rows { get; set; }
|
||||||
@@ -173,7 +176,7 @@ namespace FancyZonesEditor.Utils
|
|||||||
public int SensitivityRadius { get; set; } = LayoutSettings.DefaultSensitivityRadius;
|
public int SensitivityRadius { get; set; } = LayoutSettings.DefaultSensitivityRadius;
|
||||||
}
|
}
|
||||||
|
|
||||||
// zones-settings: custom-zone-sets
|
// custom-layouts.json
|
||||||
private struct CustomLayoutWrapper
|
private struct CustomLayoutWrapper
|
||||||
{
|
{
|
||||||
public string Uuid { get; set; }
|
public string Uuid { get; set; }
|
||||||
@@ -185,7 +188,13 @@ namespace FancyZonesEditor.Utils
|
|||||||
public JsonElement Info { get; set; } // CanvasInfoWrapper or GridInfoWrapper
|
public JsonElement Info { get; set; } // CanvasInfoWrapper or GridInfoWrapper
|
||||||
}
|
}
|
||||||
|
|
||||||
// layout-templates: templates
|
// custom-layouts.json
|
||||||
|
private struct CustomLayoutListWrapper
|
||||||
|
{
|
||||||
|
public List<CustomLayoutWrapper> CustomLayouts { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// layout-templates.json
|
||||||
private struct TemplateLayoutWrapper
|
private struct TemplateLayoutWrapper
|
||||||
{
|
{
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
@@ -199,13 +208,13 @@ namespace FancyZonesEditor.Utils
|
|||||||
public int SensitivityRadius { get; set; }
|
public int SensitivityRadius { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// layout-templates: layout-templates-wrapper
|
// layout-templates.json
|
||||||
private struct TemplateLayoutsListWrapper
|
private struct TemplateLayoutsListWrapper
|
||||||
{
|
{
|
||||||
public List<TemplateLayoutWrapper> TemplatesList { get; set; }
|
public List<TemplateLayoutWrapper> LayoutTemplates { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// layout-hotkeys: layout-hotkeys-wrapper
|
// layout-hotkeys.json
|
||||||
private struct LayoutHotkeyWrapper
|
private struct LayoutHotkeyWrapper
|
||||||
{
|
{
|
||||||
public int Key { get; set; }
|
public int Key { get; set; }
|
||||||
@@ -213,7 +222,7 @@ namespace FancyZonesEditor.Utils
|
|||||||
public string LayoutId { get; set; }
|
public string LayoutId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// layout-hotkeys: layout-hotkeys-wrapper
|
// layout-hotkeys.json
|
||||||
private struct LayoutHotkeysWrapper
|
private struct LayoutHotkeysWrapper
|
||||||
{
|
{
|
||||||
public List<LayoutHotkeyWrapper> LayoutHotkeys { get; set; }
|
public List<LayoutHotkeyWrapper> LayoutHotkeys { get; set; }
|
||||||
@@ -223,8 +232,6 @@ namespace FancyZonesEditor.Utils
|
|||||||
private struct ZoneSettingsWrapper
|
private struct ZoneSettingsWrapper
|
||||||
{
|
{
|
||||||
public List<DeviceWrapper> Devices { get; set; }
|
public List<DeviceWrapper> Devices { get; set; }
|
||||||
|
|
||||||
public List<CustomLayoutWrapper> CustomZoneSets { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct EditorParams
|
private struct EditorParams
|
||||||
@@ -258,6 +265,7 @@ namespace FancyZonesEditor.Utils
|
|||||||
FancyZonesSettingsFile = localAppDataDir + ZonesSettingsFile;
|
FancyZonesSettingsFile = localAppDataDir + ZonesSettingsFile;
|
||||||
FancyZonesLayoutHotkeysFile = localAppDataDir + LayoutHotkeysFile;
|
FancyZonesLayoutHotkeysFile = localAppDataDir + LayoutHotkeysFile;
|
||||||
FancyZonesLayoutTemplatesFile = localAppDataDir + LayoutTemplatesFile;
|
FancyZonesLayoutTemplatesFile = localAppDataDir + LayoutTemplatesFile;
|
||||||
|
FancyZonesCustomLayoutsFile = localAppDataDir + CustomLayoutsFile;
|
||||||
FancyZonesEditorParamsFile = localAppDataDir + ParamsFile;
|
FancyZonesEditorParamsFile = localAppDataDir + ParamsFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,8 +538,7 @@ namespace FancyZonesEditor.Utils
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
bool devicesParsingResult = SetDevices(zoneSettings.Devices);
|
bool devicesParsingResult = SetDevices(zoneSettings.Devices);
|
||||||
bool customZonesParsingResult = SetCustomLayouts(zoneSettings.CustomZoneSets);
|
if (!devicesParsingResult)
|
||||||
if (!devicesParsingResult || !customZonesParsingResult)
|
|
||||||
{
|
{
|
||||||
return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Zones_Settings_Message, settingsString);
|
return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Zones_Settings_Message, settingsString);
|
||||||
}
|
}
|
||||||
@@ -543,6 +550,12 @@ namespace FancyZonesEditor.Utils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var parsingCustomLayoutsResult = ParseCustomLayouts();
|
||||||
|
if (!parsingCustomLayoutsResult.Result)
|
||||||
|
{
|
||||||
|
return parsingCustomLayoutsResult;
|
||||||
|
}
|
||||||
|
|
||||||
var parsingHotkeysResult = ParseLayoutHotkeys();
|
var parsingHotkeysResult = ParseLayoutHotkeys();
|
||||||
if (!parsingHotkeysResult.Result)
|
if (!parsingHotkeysResult.Result)
|
||||||
{
|
{
|
||||||
@@ -619,7 +632,7 @@ namespace FancyZonesEditor.Utils
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
bool parsingResult = SetTemplateLayouts(templates.TemplatesList);
|
bool parsingResult = SetTemplateLayouts(templates.LayoutTemplates);
|
||||||
if (parsingResult)
|
if (parsingResult)
|
||||||
{
|
{
|
||||||
return new ParsingResult(true);
|
return new ParsingResult(true);
|
||||||
@@ -637,13 +650,52 @@ namespace FancyZonesEditor.Utils
|
|||||||
return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Layout_Templates_Message);
|
return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Layout_Templates_Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ParsingResult ParseCustomLayouts()
|
||||||
|
{
|
||||||
|
Logger.LogTrace();
|
||||||
|
|
||||||
|
if (_fileSystem.File.Exists(FancyZonesCustomLayoutsFile))
|
||||||
|
{
|
||||||
|
CustomLayoutListWrapper wrapper;
|
||||||
|
string dataString = string.Empty;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
dataString = ReadFile(FancyZonesCustomLayoutsFile);
|
||||||
|
wrapper = JsonSerializer.Deserialize<CustomLayoutListWrapper>(dataString, _options);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError("Custom layouts parsing error", ex);
|
||||||
|
return new ParsingResult(false, ex.Message, dataString);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bool parsingResult = SetCustomLayouts(wrapper.CustomLayouts);
|
||||||
|
if (parsingResult)
|
||||||
|
{
|
||||||
|
return new ParsingResult(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Custom_Layouts_Message, dataString);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError("Custom layouts parsing error", ex);
|
||||||
|
return new ParsingResult(false, ex.Message, dataString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Custom_Layouts_Message);
|
||||||
|
}
|
||||||
|
|
||||||
public void SerializeZoneSettings()
|
public void SerializeZoneSettings()
|
||||||
{
|
{
|
||||||
Logger.LogTrace();
|
Logger.LogTrace();
|
||||||
|
|
||||||
ZoneSettingsWrapper zoneSettings = new ZoneSettingsWrapper { };
|
ZoneSettingsWrapper zoneSettings = new ZoneSettingsWrapper { };
|
||||||
zoneSettings.Devices = new List<DeviceWrapper>();
|
zoneSettings.Devices = new List<DeviceWrapper>();
|
||||||
zoneSettings.CustomZoneSets = new List<CustomLayoutWrapper>();
|
|
||||||
|
|
||||||
// Serialize used devices
|
// Serialize used devices
|
||||||
foreach (var monitor in App.Overlay.Monitors)
|
foreach (var monitor in App.Overlay.Monitors)
|
||||||
@@ -675,7 +727,96 @@ namespace FancyZonesEditor.Utils
|
|||||||
zoneSettings.Devices.Add(device);
|
zoneSettings.Devices.Add(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serialize custom zonesets
|
try
|
||||||
|
{
|
||||||
|
string jsonString = JsonSerializer.Serialize(zoneSettings, _options);
|
||||||
|
_fileSystem.File.WriteAllText(FancyZonesSettingsFile, jsonString);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError("Serialize zone settings error", ex);
|
||||||
|
App.ShowExceptionMessageBox(Properties.Resources.Error_Applying_Layout, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SerializeLayoutHotkeys()
|
||||||
|
{
|
||||||
|
LayoutHotkeysWrapper hotkeys = new LayoutHotkeysWrapper { };
|
||||||
|
hotkeys.LayoutHotkeys = new List<LayoutHotkeyWrapper>();
|
||||||
|
|
||||||
|
foreach (var pair in MainWindowSettingsModel.LayoutHotkeys.SelectedKeys)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(pair.Value))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LayoutHotkeyWrapper wrapper = new LayoutHotkeyWrapper
|
||||||
|
{
|
||||||
|
Key = int.Parse(pair.Key),
|
||||||
|
LayoutId = pair.Value,
|
||||||
|
};
|
||||||
|
|
||||||
|
hotkeys.LayoutHotkeys.Add(wrapper);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError("Serialize quick layout keys error", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string jsonString = JsonSerializer.Serialize(hotkeys, _options);
|
||||||
|
_fileSystem.File.WriteAllText(FancyZonesLayoutHotkeysFile, jsonString);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError("Serialize layout hotkeys error", ex);
|
||||||
|
App.ShowExceptionMessageBox(Properties.Resources.Error_Applying_Layout, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SerializeLayoutTemplates()
|
||||||
|
{
|
||||||
|
TemplateLayoutsListWrapper templates = new TemplateLayoutsListWrapper { };
|
||||||
|
templates.LayoutTemplates = new List<TemplateLayoutWrapper>();
|
||||||
|
|
||||||
|
foreach (LayoutModel layout in MainWindowSettingsModel.DefaultModels)
|
||||||
|
{
|
||||||
|
TemplateLayoutWrapper wrapper = new TemplateLayoutWrapper
|
||||||
|
{
|
||||||
|
Type = LayoutTypeToJsonTag(layout.Type),
|
||||||
|
SensitivityRadius = layout.SensitivityRadius,
|
||||||
|
ZoneCount = layout.TemplateZoneCount,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (layout is GridLayoutModel grid)
|
||||||
|
{
|
||||||
|
wrapper.ShowSpacing = grid.ShowSpacing;
|
||||||
|
wrapper.Spacing = grid.Spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
templates.LayoutTemplates.Add(wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string jsonString = JsonSerializer.Serialize(templates, _options);
|
||||||
|
_fileSystem.File.WriteAllText(FancyZonesLayoutTemplatesFile, jsonString);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError("Serialize layout templates error", ex);
|
||||||
|
App.ShowExceptionMessageBox(Properties.Resources.Error_Applying_Layout, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SerializeCustomLayouts()
|
||||||
|
{
|
||||||
|
CustomLayoutListWrapper layouts = new CustomLayoutListWrapper { };
|
||||||
|
layouts.CustomLayouts = new List<CustomLayoutWrapper>();
|
||||||
|
|
||||||
foreach (LayoutModel layout in MainWindowSettingsModel.CustomModels)
|
foreach (LayoutModel layout in MainWindowSettingsModel.CustomModels)
|
||||||
{
|
{
|
||||||
JsonElement info;
|
JsonElement info;
|
||||||
@@ -758,90 +899,17 @@ namespace FancyZonesEditor.Utils
|
|||||||
Info = info,
|
Info = info,
|
||||||
};
|
};
|
||||||
|
|
||||||
zoneSettings.CustomZoneSets.Add(customLayout);
|
layouts.CustomLayouts.Add(customLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string jsonString = JsonSerializer.Serialize(zoneSettings, _options);
|
string jsonString = JsonSerializer.Serialize(layouts, _options);
|
||||||
_fileSystem.File.WriteAllText(FancyZonesSettingsFile, jsonString);
|
_fileSystem.File.WriteAllText(FancyZonesCustomLayoutsFile, jsonString);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.LogError("Serialize zone settings error", ex);
|
Logger.LogError("Serialize custom layouts error", ex);
|
||||||
App.ShowExceptionMessageBox(Properties.Resources.Error_Applying_Layout, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SerializeLayoutHotkeys()
|
|
||||||
{
|
|
||||||
LayoutHotkeysWrapper hotkeys = new LayoutHotkeysWrapper { };
|
|
||||||
hotkeys.LayoutHotkeys = new List<LayoutHotkeyWrapper>();
|
|
||||||
|
|
||||||
foreach (var pair in MainWindowSettingsModel.LayoutHotkeys.SelectedKeys)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(pair.Value))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
LayoutHotkeyWrapper wrapper = new LayoutHotkeyWrapper
|
|
||||||
{
|
|
||||||
Key = int.Parse(pair.Key),
|
|
||||||
LayoutId = pair.Value,
|
|
||||||
};
|
|
||||||
|
|
||||||
hotkeys.LayoutHotkeys.Add(wrapper);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogError("Serialize quick layout keys error", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string jsonString = JsonSerializer.Serialize(hotkeys, _options);
|
|
||||||
_fileSystem.File.WriteAllText(FancyZonesLayoutHotkeysFile, jsonString);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogError("Serialize layout hotkeys error", ex);
|
|
||||||
App.ShowExceptionMessageBox(Properties.Resources.Error_Applying_Layout, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SerializeLayoutTemplates()
|
|
||||||
{
|
|
||||||
TemplateLayoutsListWrapper templates = new TemplateLayoutsListWrapper { };
|
|
||||||
templates.TemplatesList = new List<TemplateLayoutWrapper>();
|
|
||||||
|
|
||||||
foreach (LayoutModel layout in MainWindowSettingsModel.DefaultModels)
|
|
||||||
{
|
|
||||||
TemplateLayoutWrapper wrapper = new TemplateLayoutWrapper
|
|
||||||
{
|
|
||||||
Type = LayoutTypeToJsonTag(layout.Type),
|
|
||||||
SensitivityRadius = layout.SensitivityRadius,
|
|
||||||
ZoneCount = layout.TemplateZoneCount,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (layout is GridLayoutModel grid)
|
|
||||||
{
|
|
||||||
wrapper.ShowSpacing = grid.ShowSpacing;
|
|
||||||
wrapper.Spacing = grid.Spacing;
|
|
||||||
}
|
|
||||||
|
|
||||||
templates.TemplatesList.Add(wrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string jsonString = JsonSerializer.Serialize(templates, _options);
|
|
||||||
_fileSystem.File.WriteAllText(FancyZonesLayoutTemplatesFile, jsonString);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogError("Serialize layout templates error", ex);
|
|
||||||
App.ShowExceptionMessageBox(Properties.Resources.Error_Applying_Layout, ex);
|
App.ShowExceptionMessageBox(Properties.Resources.Error_Applying_Layout, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user