mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-15 19:27:56 +01:00
[FancyZones] Customize default layouts (#21156)
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
#include <FancyZonesLib/FancyZonesData/AppliedLayouts.h>
|
||||
#include <FancyZonesLib/FancyZonesData/AppZoneHistory.h>
|
||||
#include <FancyZonesLib/FancyZonesData/CustomLayouts.h>
|
||||
#include <FancyZonesLib/FancyZonesData/DefaultLayouts.h>
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutHotkeys.h>
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutTemplates.h>
|
||||
#include <FancyZonesLib/FancyZonesWindowProcessing.h>
|
||||
@@ -73,6 +74,7 @@ public:
|
||||
LayoutHotkeys::instance().LoadData();
|
||||
AppliedLayouts::instance().LoadData();
|
||||
AppZoneHistory::instance().LoadData();
|
||||
DefaultLayouts::instance().LoadData();
|
||||
}
|
||||
|
||||
// IFancyZones
|
||||
@@ -662,6 +664,10 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
|
||||
AppliedLayouts::instance().LoadData();
|
||||
UpdateZoneSets();
|
||||
}
|
||||
else if (message == WM_PRIV_DEFAULT_LAYOUTS_FILE_UPDATE)
|
||||
{
|
||||
DefaultLayouts::instance().LoadData();
|
||||
}
|
||||
else if (message == WM_PRIV_QUICK_LAYOUT_KEY)
|
||||
{
|
||||
ApplyQuickLayout(static_cast<int>(lparam));
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <FancyZonesLib/GuidUtils.h>
|
||||
#include <FancyZonesLib/FancyZonesData/CustomLayouts.h>
|
||||
#include <FancyZonesLib/FancyZonesData/DefaultLayouts.h>
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutDefaults.h>
|
||||
#include <FancyZonesLib/FancyZonesWinHookEventIDs.h>
|
||||
#include <FancyZonesLib/JsonHelpers.h>
|
||||
@@ -73,7 +74,7 @@ namespace JsonUtils
|
||||
struct AppliedLayoutsJSON
|
||||
{
|
||||
private:
|
||||
static std::optional<FancyZonesDataTypes::WorkAreaId> WorkAreaIdFromJson(const json::JsonObject& json)
|
||||
static std::pair<std::optional<FancyZonesDataTypes::WorkAreaId>, bool> WorkAreaIdFromJson(const json::JsonObject& json)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -89,7 +90,7 @@ namespace JsonUtils
|
||||
auto virtualDesktopGuid = FancyZonesUtils::GuidFromString(virtualDesktop);
|
||||
if (!virtualDesktopGuid)
|
||||
{
|
||||
return std::nullopt;
|
||||
return { std::nullopt, false };
|
||||
}
|
||||
|
||||
FancyZonesDataTypes::DeviceId deviceId{};
|
||||
@@ -104,16 +105,17 @@ namespace JsonUtils
|
||||
deviceId.instanceId = monitorInstance;
|
||||
deviceId.number = monitorNumber;
|
||||
}
|
||||
|
||||
|
||||
FancyZonesDataTypes::MonitorId monitorId{
|
||||
.deviceId = deviceId,
|
||||
.serialNumber = monitorSerialNumber
|
||||
};
|
||||
|
||||
return FancyZonesDataTypes::WorkAreaId{
|
||||
.monitorId = monitorId,
|
||||
.virtualDesktopId = virtualDesktopGuid.value(),
|
||||
};
|
||||
return { FancyZonesDataTypes::WorkAreaId{
|
||||
.monitorId = monitorId,
|
||||
.virtualDesktopId = virtualDesktopGuid.value(),
|
||||
},
|
||||
false };
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -121,24 +123,26 @@ namespace JsonUtils
|
||||
auto bcDeviceId = BackwardsCompatibility::DeviceIdData::ParseDeviceId(deviceIdStr);
|
||||
if (!bcDeviceId)
|
||||
{
|
||||
return std::nullopt;
|
||||
return { std::nullopt, false };
|
||||
}
|
||||
|
||||
return FancyZonesDataTypes::WorkAreaId{
|
||||
.monitorId = { .deviceId = MonitorUtils::Display::ConvertObsoleteDeviceId(bcDeviceId->deviceName) },
|
||||
.virtualDesktopId = bcDeviceId->virtualDesktopId,
|
||||
};
|
||||
return { FancyZonesDataTypes::WorkAreaId{
|
||||
.monitorId = { .deviceId = MonitorUtils::Display::ConvertObsoleteDeviceId(bcDeviceId->deviceName) },
|
||||
.virtualDesktopId = bcDeviceId->virtualDesktopId,
|
||||
},
|
||||
true };
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
{
|
||||
return std::nullopt;
|
||||
return { std::nullopt, false };
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
FancyZonesDataTypes::WorkAreaId workAreaId;
|
||||
Layout data{};
|
||||
bool hasResolutionInId = false;
|
||||
|
||||
static std::optional<AppliedLayoutsJSON> FromJson(const json::JsonObject& json)
|
||||
{
|
||||
@@ -147,7 +151,7 @@ namespace JsonUtils
|
||||
AppliedLayoutsJSON result;
|
||||
|
||||
auto deviceIdOpt = WorkAreaIdFromJson(json);
|
||||
if (!deviceIdOpt.has_value())
|
||||
if (!deviceIdOpt.first.has_value())
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -158,8 +162,10 @@ namespace JsonUtils
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
result.workAreaId = std::move(deviceIdOpt.value());
|
||||
result.workAreaId = std::move(deviceIdOpt.first.value());
|
||||
result.data = std::move(layout.value());
|
||||
result.hasResolutionInId = deviceIdOpt.second;
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
@@ -200,8 +206,13 @@ namespace JsonUtils
|
||||
if (auto obj = AppliedLayoutsJSON::FromJson(layouts.GetObjectAt(i)); obj.has_value())
|
||||
{
|
||||
// skip default layouts in case if they were applied to different resolutions on the same monitor.
|
||||
// NOTE: keep the default layout check for users who update PT version from the v0.57
|
||||
if (!map.contains(obj->workAreaId) && !isLayoutDefault(obj->data))
|
||||
// NOTE: keep the default layout check for users who update PT version from the v0.57
|
||||
if (obj->hasResolutionInId && isLayoutDefault(obj->data))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!map.contains(obj->workAreaId))
|
||||
{
|
||||
map[obj->workAreaId] = std::move(obj->data);
|
||||
}
|
||||
@@ -456,16 +467,8 @@ bool AppliedLayouts::ApplyDefaultLayout(const FancyZonesDataTypes::WorkAreaId& d
|
||||
return false;
|
||||
}
|
||||
|
||||
Layout layout{
|
||||
.uuid = guid,
|
||||
.type = FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid,
|
||||
.showSpacing = DefaultValues::ShowSpacing,
|
||||
.spacing = DefaultValues::Spacing,
|
||||
.zoneCount = DefaultValues::ZoneCount,
|
||||
.sensitivityRadius = DefaultValues::SensitivityRadius
|
||||
};
|
||||
|
||||
m_layouts[deviceId] = std::move(layout);
|
||||
// TODO: vertical or horizontal
|
||||
m_layouts[deviceId] = DefaultLayouts::instance().GetDefaultLayout();
|
||||
|
||||
// Saving default layout data doesn't make sense, since it's ignored on parsing.
|
||||
// Given that default layouts are ignored when parsing,
|
||||
|
||||
@@ -227,11 +227,7 @@ std::optional<Layout> CustomLayouts::GetLayout(const GUID& id) const noexcept
|
||||
FancyZonesDataTypes::CustomLayoutData customLayout = iter->second;
|
||||
Layout layout{
|
||||
.uuid = id,
|
||||
.type = FancyZonesDataTypes::ZoneSetLayoutType::Custom,
|
||||
.showSpacing = DefaultValues::ShowSpacing,
|
||||
.spacing = DefaultValues::Spacing,
|
||||
.zoneCount = DefaultValues::ZoneCount,
|
||||
.sensitivityRadius = DefaultValues::SensitivityRadius
|
||||
.type = FancyZonesDataTypes::ZoneSetLayoutType::Custom
|
||||
};
|
||||
|
||||
if (customLayout.type == FancyZonesDataTypes::CustomLayoutType::Grid)
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
#include "../pch.h"
|
||||
#include "DefaultLayouts.h"
|
||||
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutDefaults.h>
|
||||
#include <FancyZonesLib/FancyZonesWinHookEventIDs.h>
|
||||
#include <FancyZonesLib/util.h>
|
||||
|
||||
#include <common/logger/logger.h>
|
||||
|
||||
namespace DefaultLayoutsJsonUtils
|
||||
{
|
||||
MonitorConfiguraionType TypeFromString(const std::wstring& data)
|
||||
{
|
||||
if (data == L"vertical")
|
||||
{
|
||||
return MonitorConfiguraionType::Vertical;
|
||||
}
|
||||
|
||||
return MonitorConfiguraionType::Horizontal;
|
||||
}
|
||||
|
||||
std::wstring TypeToString(MonitorConfiguraionType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MonitorConfiguraionType::Horizontal:
|
||||
return L"horizontal";
|
||||
case MonitorConfiguraionType::Vertical:
|
||||
return L"vertical";
|
||||
default:
|
||||
return L"horizontal";
|
||||
}
|
||||
}
|
||||
|
||||
struct LayoutJSON
|
||||
{
|
||||
static std::optional<Layout> FromJson(const json::JsonObject& json)
|
||||
{
|
||||
try
|
||||
{
|
||||
Layout data{};
|
||||
auto idStr = json.GetNamedString(NonLocalizable::DefaultLayoutsIds::UuidID, L"");
|
||||
if (!idStr.empty())
|
||||
{
|
||||
auto id = FancyZonesUtils::GuidFromString(idStr.c_str());
|
||||
if (!id.has_value())
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
data.uuid = id.value();
|
||||
}
|
||||
|
||||
data.type = FancyZonesDataTypes::TypeFromString(std::wstring{ json.GetNamedString(NonLocalizable::DefaultLayoutsIds::TypeID) });
|
||||
data.showSpacing = json.GetNamedBoolean(NonLocalizable::DefaultLayoutsIds::ShowSpacingID, DefaultValues::ShowSpacing);
|
||||
data.spacing = static_cast<int>(json.GetNamedNumber(NonLocalizable::DefaultLayoutsIds::SpacingID, DefaultValues::Spacing));
|
||||
data.zoneCount = static_cast<int>(json.GetNamedNumber(NonLocalizable::DefaultLayoutsIds::ZoneCountID, DefaultValues::ZoneCount));
|
||||
data.sensitivityRadius = static_cast<int>(json.GetNamedNumber(NonLocalizable::DefaultLayoutsIds::SensitivityRadiusID, DefaultValues::SensitivityRadius));
|
||||
|
||||
return data;
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
static json::JsonObject ToJson(const Layout& data)
|
||||
{
|
||||
json::JsonObject result{};
|
||||
result.SetNamedValue(NonLocalizable::DefaultLayoutsIds::UuidID, json::value(FancyZonesUtils::GuidToString(data.uuid).value()));
|
||||
result.SetNamedValue(NonLocalizable::DefaultLayoutsIds::TypeID, json::value(FancyZonesDataTypes::TypeToString(data.type)));
|
||||
result.SetNamedValue(NonLocalizable::DefaultLayoutsIds::ShowSpacingID, json::value(data.showSpacing));
|
||||
result.SetNamedValue(NonLocalizable::DefaultLayoutsIds::SpacingID, json::value(data.spacing));
|
||||
result.SetNamedValue(NonLocalizable::DefaultLayoutsIds::ZoneCountID, json::value(data.zoneCount));
|
||||
result.SetNamedValue(NonLocalizable::DefaultLayoutsIds::SensitivityRadiusID, json::value(data.sensitivityRadius));
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
struct DefaultLayoutJSON
|
||||
{
|
||||
MonitorConfiguraionType monitorConfigurationType{ MonitorConfiguraionType::Horizontal };
|
||||
Layout layout{};
|
||||
|
||||
static std::optional<DefaultLayoutJSON> FromJson(const json::JsonObject& json)
|
||||
{
|
||||
try
|
||||
{
|
||||
DefaultLayoutJSON result;
|
||||
|
||||
auto type = TypeFromString(std::wstring{ json.GetNamedString(NonLocalizable::DefaultLayoutsIds::MonitorConfigurationTypeID) });
|
||||
auto layout = DefaultLayoutsJsonUtils::LayoutJSON::FromJson(json.GetNamedObject(NonLocalizable::DefaultLayoutsIds::LayoutID));
|
||||
if (!layout.has_value())
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
result.monitorConfigurationType = std::move(type);
|
||||
result.layout = std::move(layout.value());
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DefaultLayouts::TDefaultLayoutsContainer ParseJson(const json::JsonObject& json)
|
||||
{
|
||||
DefaultLayouts::TDefaultLayoutsContainer map{};
|
||||
auto layouts = json.GetNamedArray(NonLocalizable::DefaultLayoutsIds::DefaultLayoutsArrayID);
|
||||
|
||||
for (uint32_t i = 0; i < layouts.Size(); ++i)
|
||||
{
|
||||
if (auto obj = DefaultLayoutJSON::FromJson(layouts.GetObjectAt(i)); obj.has_value())
|
||||
{
|
||||
map[static_cast<MonitorConfiguraionType>(obj->monitorConfigurationType)] = std::move(obj->layout);
|
||||
}
|
||||
}
|
||||
|
||||
return std::move(map);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DefaultLayouts::DefaultLayouts()
|
||||
{
|
||||
const std::wstring& dataFileName = DefaultLayoutsFileName();
|
||||
m_fileWatcher = std::make_unique<FileWatcher>(dataFileName, [&]() {
|
||||
PostMessageW(HWND_BROADCAST, WM_PRIV_DEFAULT_LAYOUTS_FILE_UPDATE, NULL, NULL);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
DefaultLayouts& DefaultLayouts::instance()
|
||||
{
|
||||
static DefaultLayouts self;
|
||||
return self;
|
||||
}
|
||||
|
||||
void DefaultLayouts::LoadData()
|
||||
{
|
||||
auto data = json::from_file(DefaultLayoutsFileName());
|
||||
|
||||
try
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
m_layouts = DefaultLayoutsJsonUtils::ParseJson(data.value());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_layouts.clear();
|
||||
Logger::info(L"default-layouts.json file is missing or malformed");
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error& e)
|
||||
{
|
||||
Logger::error(L"Parsing default-layouts error: {}", e.message());
|
||||
}
|
||||
}
|
||||
|
||||
Layout DefaultLayouts::GetDefaultLayout(MonitorConfiguraionType type) const noexcept
|
||||
{
|
||||
auto iter = m_layouts.find(type);
|
||||
if (iter != m_layouts.end())
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
return Layout{};
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <FancyZonesLib/FancyZonesData/Layout.h>
|
||||
#include <FancyZonesLib/ModuleConstants.h>
|
||||
|
||||
#include <common/SettingsAPI/FileWatcher.h>
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
|
||||
namespace NonLocalizable
|
||||
{
|
||||
namespace DefaultLayoutsIds
|
||||
{
|
||||
const static wchar_t* DefaultLayoutsArrayID = L"default-layouts";
|
||||
const static wchar_t* MonitorConfigurationTypeID = L"monitor-configuration";
|
||||
const static wchar_t* LayoutID = L"layout";
|
||||
const static wchar_t* UuidID = L"uuid";
|
||||
const static wchar_t* TypeID = L"type";
|
||||
const static wchar_t* ShowSpacingID = L"show-spacing";
|
||||
const static wchar_t* SpacingID = L"spacing";
|
||||
const static wchar_t* ZoneCountID = L"zone-count";
|
||||
const static wchar_t* SensitivityRadiusID = L"sensitivity-radius";
|
||||
}
|
||||
}
|
||||
|
||||
enum class MonitorConfiguraionType
|
||||
{
|
||||
Horizontal = 0,
|
||||
Vertical
|
||||
};
|
||||
|
||||
class DefaultLayouts
|
||||
{
|
||||
public:
|
||||
using TDefaultLayoutsContainer = std::map<MonitorConfiguraionType, Layout>;
|
||||
|
||||
static DefaultLayouts& instance();
|
||||
|
||||
inline static std::wstring DefaultLayoutsFileName()
|
||||
{
|
||||
std::wstring saveFolderPath = PTSettingsHelper::get_module_save_folder_location(NonLocalizable::ModuleKey);
|
||||
#if defined(UNIT_TESTS)
|
||||
return saveFolderPath + L"\\test-default-layouts.json";
|
||||
#endif
|
||||
return saveFolderPath + L"\\default-layouts.json";
|
||||
}
|
||||
|
||||
void LoadData();
|
||||
|
||||
Layout GetDefaultLayout(MonitorConfiguraionType type = MonitorConfiguraionType::Horizontal) const noexcept;
|
||||
|
||||
private:
|
||||
DefaultLayouts();
|
||||
~DefaultLayouts() = default;
|
||||
|
||||
TDefaultLayoutsContainer m_layouts;
|
||||
std::unique_ptr<FileWatcher> m_fileWatcher;
|
||||
};
|
||||
@@ -2,14 +2,25 @@
|
||||
|
||||
#include <guiddef.h>
|
||||
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutDefaults.h>
|
||||
#include <FancyZonesLib/FancyZonesDataTypes.h>
|
||||
|
||||
struct Layout
|
||||
{
|
||||
GUID uuid;
|
||||
FancyZonesDataTypes::ZoneSetLayoutType type;
|
||||
bool showSpacing;
|
||||
int spacing;
|
||||
int zoneCount;
|
||||
int sensitivityRadius;
|
||||
};
|
||||
GUID uuid = GUID_NULL;
|
||||
FancyZonesDataTypes::ZoneSetLayoutType type = FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid;
|
||||
bool showSpacing = DefaultValues::ShowSpacing;
|
||||
int spacing = DefaultValues::Spacing;
|
||||
int zoneCount = DefaultValues::ZoneCount;
|
||||
int sensitivityRadius = DefaultValues::SensitivityRadius;
|
||||
};
|
||||
|
||||
inline bool operator==(const Layout& lhs, const Layout& rhs)
|
||||
{
|
||||
return lhs.uuid == rhs.uuid &&
|
||||
lhs.type == rhs.type &&
|
||||
lhs.showSpacing == rhs.showSpacing &&
|
||||
lhs.spacing == rhs.spacing &&
|
||||
lhs.zoneCount == rhs.zoneCount &&
|
||||
lhs.sensitivityRadius == rhs.sensitivityRadius;
|
||||
}
|
||||
@@ -41,6 +41,7 @@
|
||||
<ClInclude Include="FancyZonesData\AppZoneHistory.h" />
|
||||
<ClInclude Include="FancyZones.h" />
|
||||
<ClInclude Include="FancyZonesDataTypes.h" />
|
||||
<ClInclude Include="FancyZonesData\DefaultLayouts.h" />
|
||||
<ClInclude Include="FancyZonesData\Layout.h" />
|
||||
<ClInclude Include="FancyZonesData\LayoutDefaults.h" />
|
||||
<ClInclude Include="FancyZonesData\LayoutTemplates.h" />
|
||||
@@ -90,6 +91,9 @@
|
||||
<ClCompile Include="FancyZonesData\AppliedLayouts.cpp">
|
||||
<PrecompiledHeaderFile>../pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesData\DefaultLayouts.cpp">
|
||||
<PrecompiledHeaderFile>../pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesData\LayoutTemplates.cpp">
|
||||
<PrecompiledHeaderFile>../pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
<Filter Include="Generated Files">
|
||||
<UniqueIdentifier>{093625ff-2415-4c2c-842c-0ee7fcb1d203}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\FancyZonesData">
|
||||
<UniqueIdentifier>{dcbd2932-a3b2-400a-ad0d-6315f9795b13}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\FancyZonesData">
|
||||
<UniqueIdentifier>{5b35a312-b878-49e9-92c0-e098c2b97deb}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
@@ -90,30 +96,9 @@
|
||||
<ClInclude Include="GuidUtils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\AppZoneHistory.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\AppliedLayouts.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\CustomLayouts.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\LayoutHotkeys.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ModuleConstants.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\LayoutTemplates.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\LayoutDefaults.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\Layout.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ZoneIndexSetBitmask.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -132,6 +117,30 @@
|
||||
<ClInclude Include="FancyZonesWindowProcessing.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\AppliedLayouts.h">
|
||||
<Filter>Header Files\FancyZonesData</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\AppZoneHistory.h">
|
||||
<Filter>Header Files\FancyZonesData</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\CustomLayouts.h">
|
||||
<Filter>Header Files\FancyZonesData</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\DefaultLayouts.h">
|
||||
<Filter>Header Files\FancyZonesData</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\Layout.h">
|
||||
<Filter>Header Files\FancyZonesData</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\LayoutDefaults.h">
|
||||
<Filter>Header Files\FancyZonesData</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\LayoutHotkeys.h">
|
||||
<Filter>Header Files\FancyZonesData</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FancyZonesData\LayoutTemplates.h">
|
||||
<Filter>Header Files\FancyZonesData</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="EditorParameters.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -194,21 +203,6 @@
|
||||
<ClCompile Include="MonitorUtils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesData\CustomLayouts.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesData\LayoutHotkeys.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesData\AppZoneHistory.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesData\AppliedLayouts.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesData\LayoutTemplates.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesWindowProperties.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@@ -224,6 +218,24 @@
|
||||
<ClCompile Include="EditorParameters.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesData\AppliedLayouts.cpp">
|
||||
<Filter>Source Files\FancyZonesData</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesData\AppZoneHistory.cpp">
|
||||
<Filter>Source Files\FancyZonesData</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesData\CustomLayouts.cpp">
|
||||
<Filter>Source Files\FancyZonesData</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesData\DefaultLayouts.cpp">
|
||||
<Filter>Source Files\FancyZonesData</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesData\LayoutHotkeys.cpp">
|
||||
<Filter>Source Files\FancyZonesData</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FancyZonesData\LayoutTemplates.cpp">
|
||||
<Filter>Source Files\FancyZonesData</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
||||
@@ -15,6 +15,7 @@ UINT WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE;
|
||||
UINT WM_PRIV_LAYOUT_TEMPLATES_FILE_UPDATE;
|
||||
UINT WM_PRIV_CUSTOM_LAYOUTS_FILE_UPDATE;
|
||||
UINT WM_PRIV_APPLIED_LAYOUTS_FILE_UPDATE;
|
||||
UINT WM_PRIV_DEFAULT_LAYOUTS_FILE_UPDATE;
|
||||
UINT WM_PRIV_SNAP_HOTKEY;
|
||||
UINT WM_PRIV_QUICK_LAYOUT_KEY;
|
||||
UINT WM_PRIV_SETTINGS_CHANGED;
|
||||
@@ -37,6 +38,7 @@ void InitializeWinhookEventIds()
|
||||
WM_PRIV_LAYOUT_TEMPLATES_FILE_UPDATE = RegisterWindowMessage(L"{4686f019-5d3d-4c5c-9051-b7cbbccca77d}");
|
||||
WM_PRIV_CUSTOM_LAYOUTS_FILE_UPDATE = RegisterWindowMessage(L"{0972787e-cdab-4e16-b228-91acdc38f40f}");
|
||||
WM_PRIV_APPLIED_LAYOUTS_FILE_UPDATE = RegisterWindowMessage(L"{2ef2c8a7-e0d5-4f31-9ede-52aade2d284d}");
|
||||
WM_PRIV_DEFAULT_LAYOUTS_FILE_UPDATE = RegisterWindowMessage(L"{61fd2afb-e909-41b2-b6f3-b9f546f2ae3f}");
|
||||
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_SETTINGS_CHANGED = RegisterWindowMessage(L"{89ca3Daa-bf2d-4e73-9f3f-c60716364e27}");
|
||||
|
||||
@@ -13,6 +13,7 @@ extern UINT WM_PRIV_LAYOUT_HOTKEYS_FILE_UPDATE; // Scheduled when the watched la
|
||||
extern UINT WM_PRIV_LAYOUT_TEMPLATES_FILE_UPDATE; // Scheduled when the watched layout-templates.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_APPLIED_LAYOUTS_FILE_UPDATE; // Scheduled when the watched applied-layouts.json file is updated
|
||||
extern UINT WM_PRIV_DEFAULT_LAYOUTS_FILE_UPDATE; // Scheduled when the watched default-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_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
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
#include "pch.h"
|
||||
#include <filesystem>
|
||||
|
||||
#include <FancyZonesLib/FancyZonesData/DefaultLayouts.h>
|
||||
#include <FancyZonesLib/FancyZonesData/LayoutDefaults.h>
|
||||
#include <FancyZonesLib/util.h>
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
|
||||
namespace FancyZonesUnitTests
|
||||
{
|
||||
TEST_CLASS (DefaultLayoutsUnitTests)
|
||||
{
|
||||
std::wstring m_testFolder = L"FancyZonesUnitTests";
|
||||
std::wstring m_testFolderPath = PTSettingsHelper::get_module_save_folder_location(m_testFolder);
|
||||
|
||||
TEST_METHOD_CLEANUP(CleanUp)
|
||||
{
|
||||
std::filesystem::remove(DefaultLayouts::DefaultLayoutsFileName());
|
||||
std::filesystem::remove_all(m_testFolderPath);
|
||||
}
|
||||
|
||||
TEST_METHOD (DefaultLayoutsParse)
|
||||
{
|
||||
// prepare
|
||||
json::JsonObject root{};
|
||||
json::JsonArray layoutsArray{};
|
||||
|
||||
// custom, horizontal
|
||||
{
|
||||
json::JsonObject layout{};
|
||||
layout.SetNamedValue(NonLocalizable::DefaultLayoutsIds::UuidID, json::value(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}"));
|
||||
layout.SetNamedValue(NonLocalizable::DefaultLayoutsIds::TypeID, json::value(L"custom"));
|
||||
|
||||
json::JsonObject obj{};
|
||||
obj.SetNamedValue(NonLocalizable::DefaultLayoutsIds::MonitorConfigurationTypeID, json::value(L"horizontal"));
|
||||
obj.SetNamedValue(NonLocalizable::DefaultLayoutsIds::LayoutID, layout);
|
||||
layoutsArray.Append(obj);
|
||||
}
|
||||
|
||||
// template, vertical
|
||||
{
|
||||
json::JsonObject layout{};
|
||||
layout.SetNamedValue(NonLocalizable::DefaultLayoutsIds::TypeID, json::value(L"grid"));
|
||||
layout.SetNamedValue(NonLocalizable::DefaultLayoutsIds::ShowSpacingID, json::value(true));
|
||||
layout.SetNamedValue(NonLocalizable::DefaultLayoutsIds::SpacingID, json::value(1));
|
||||
layout.SetNamedValue(NonLocalizable::DefaultLayoutsIds::ZoneCountID, json::value(4));
|
||||
layout.SetNamedValue(NonLocalizable::DefaultLayoutsIds::SensitivityRadiusID, json::value(30));
|
||||
|
||||
json::JsonObject obj{};
|
||||
obj.SetNamedValue(NonLocalizable::DefaultLayoutsIds::MonitorConfigurationTypeID, json::value(L"vertical"));
|
||||
obj.SetNamedValue(NonLocalizable::DefaultLayoutsIds::LayoutID, layout);
|
||||
layoutsArray.Append(obj);
|
||||
}
|
||||
|
||||
root.SetNamedValue(NonLocalizable::DefaultLayoutsIds::DefaultLayoutsArrayID, layoutsArray);
|
||||
json::to_file(DefaultLayouts::DefaultLayoutsFileName(), root);
|
||||
|
||||
// test
|
||||
DefaultLayouts::instance().LoadData();
|
||||
|
||||
Layout horizontal{
|
||||
.uuid = FancyZonesUtils::GuidFromString(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}").value(),
|
||||
.type = FancyZonesDataTypes::ZoneSetLayoutType::Custom
|
||||
};
|
||||
Assert::IsTrue(horizontal == DefaultLayouts::instance().GetDefaultLayout(MonitorConfiguraionType::Horizontal));
|
||||
|
||||
Layout vertical{
|
||||
.uuid = GUID_NULL,
|
||||
.type = FancyZonesDataTypes::ZoneSetLayoutType::Grid,
|
||||
.showSpacing = true,
|
||||
.spacing = 1,
|
||||
.zoneCount = 4,
|
||||
.sensitivityRadius = 30
|
||||
};
|
||||
Assert::IsTrue(vertical == DefaultLayouts::instance().GetDefaultLayout(MonitorConfiguraionType::Vertical));
|
||||
}
|
||||
|
||||
TEST_METHOD (DefaultLayoutsParseEmpty)
|
||||
{
|
||||
// prepare
|
||||
json::JsonObject root{};
|
||||
json::JsonArray layoutsArray{};
|
||||
root.SetNamedValue(NonLocalizable::DefaultLayoutsIds::DefaultLayoutsArrayID, layoutsArray);
|
||||
json::to_file(DefaultLayouts::DefaultLayoutsFileName(), root);
|
||||
|
||||
// test
|
||||
DefaultLayouts::instance().LoadData();
|
||||
|
||||
Layout priorityGrid{
|
||||
.uuid = GUID_NULL,
|
||||
.type = FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid,
|
||||
.showSpacing = DefaultValues::ShowSpacing,
|
||||
.spacing = DefaultValues::Spacing,
|
||||
.zoneCount = DefaultValues::ZoneCount,
|
||||
.sensitivityRadius = DefaultValues::SensitivityRadius
|
||||
};
|
||||
|
||||
Assert::IsTrue(priorityGrid == DefaultLayouts::instance().GetDefaultLayout(MonitorConfiguraionType::Horizontal));
|
||||
Assert::IsTrue(priorityGrid == DefaultLayouts::instance().GetDefaultLayout(MonitorConfiguraionType::Vertical));
|
||||
}
|
||||
|
||||
TEST_METHOD (DefaultLayoutsNoFile)
|
||||
{
|
||||
// test
|
||||
DefaultLayouts::instance().LoadData();
|
||||
|
||||
Layout priorityGrid{
|
||||
.uuid = GUID_NULL,
|
||||
.type = FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid,
|
||||
.showSpacing = DefaultValues::ShowSpacing,
|
||||
.spacing = DefaultValues::Spacing,
|
||||
.zoneCount = DefaultValues::ZoneCount,
|
||||
.sensitivityRadius = DefaultValues::SensitivityRadius
|
||||
};
|
||||
|
||||
Assert::IsTrue(priorityGrid == DefaultLayouts::instance().GetDefaultLayout(MonitorConfiguraionType::Horizontal));
|
||||
Assert::IsTrue(priorityGrid == DefaultLayouts::instance().GetDefaultLayout(MonitorConfiguraionType::Vertical));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -44,6 +44,7 @@
|
||||
<ClCompile Include="AppliedLayoutsTests.Spec.cpp" />
|
||||
<ClCompile Include="AppZoneHistoryTests.Spec.cpp" />
|
||||
<ClCompile Include="CustomLayoutsTests.Spec.cpp" />
|
||||
<ClCompile Include="DefaultLayoutsTests.Spec.cpp" />
|
||||
<ClCompile Include="FancyZonesSettings.Spec.cpp" />
|
||||
<ClCompile Include="JsonHelpers.Tests.cpp" />
|
||||
<ClCompile Include="LayoutHotkeysTests.Spec.cpp" />
|
||||
|
||||
@@ -57,6 +57,9 @@
|
||||
<ClCompile Include="WorkAreaIdTests.Spec.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DefaultLayoutsTests.Spec.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
|
||||
@@ -2,20 +2,14 @@
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include <FancyZonesLib/util.h>
|
||||
#include <FancyZonesLib/ZoneSet.h>
|
||||
#include <FancyZonesLib/WorkArea.h>
|
||||
#include <FancyZonesLib/FancyZones.h>
|
||||
#include <FancyZonesLib/FancyZonesData/AppliedLayouts.h>
|
||||
#include <FancyZonesLib/FancyZonesData/AppZoneHistory.h>
|
||||
#include <FancyZonesLib/FancyZonesDataTypes.h>
|
||||
#include <FancyZonesLib/JsonHelpers.h>
|
||||
#include <FancyZonesLib/FancyZonesData/DefaultLayouts.h>
|
||||
#include "Util.h"
|
||||
|
||||
#include <common/utils/process_path.h>
|
||||
|
||||
#include <CppUnitTestLogger.h>
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
|
||||
namespace FancyZonesUnitTests
|
||||
@@ -40,36 +34,43 @@ namespace FancyZonesUnitTests
|
||||
|
||||
AppZoneHistory::instance().LoadData();
|
||||
AppliedLayouts::instance().LoadData();
|
||||
DefaultLayouts::instance().LoadData();
|
||||
}
|
||||
|
||||
TEST_METHOD_CLEANUP(CleanUp)
|
||||
{
|
||||
std::filesystem::remove(AppliedLayouts::AppliedLayoutsFileName());
|
||||
std::filesystem::remove(AppZoneHistory::AppZoneHistoryFileName());
|
||||
|
||||
std::filesystem::remove(DefaultLayouts::DefaultLayoutsFileName());
|
||||
}
|
||||
|
||||
TEST_METHOD (CreateWorkArea)
|
||||
{
|
||||
const auto defaultLayout = DefaultLayouts::instance().GetDefaultLayout();
|
||||
|
||||
auto workArea = MakeWorkArea({}, Mocks::Monitor(), m_uniqueId, m_emptyUniqueId);
|
||||
Assert::IsFalse(workArea == nullptr);
|
||||
Assert::IsTrue(m_uniqueId == workArea->UniqueId());
|
||||
|
||||
auto* zoneSet{ workArea->ZoneSet() };
|
||||
Assert::IsNotNull(zoneSet);
|
||||
Assert::AreEqual(static_cast<int>(zoneSet->LayoutType()), static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid));
|
||||
Assert::AreEqual(zoneSet->GetZones().size(), static_cast<size_t>(3));
|
||||
Assert::AreEqual(static_cast<int>(defaultLayout.type), static_cast<int>(zoneSet->LayoutType()));
|
||||
Assert::AreEqual(static_cast<size_t>(defaultLayout.zoneCount), zoneSet->GetZones().size());
|
||||
}
|
||||
|
||||
TEST_METHOD (CreateCombinedWorkArea)
|
||||
{
|
||||
const auto defaultLayout = DefaultLayouts::instance().GetDefaultLayout();
|
||||
|
||||
auto workArea = MakeWorkArea({}, {}, m_uniqueId, m_emptyUniqueId);
|
||||
Assert::IsFalse(workArea == nullptr);
|
||||
Assert::IsTrue(m_uniqueId == workArea->UniqueId());
|
||||
|
||||
auto* zoneSet{ workArea->ZoneSet() };
|
||||
Assert::IsNotNull(zoneSet);
|
||||
Assert::AreEqual(static_cast<int>(zoneSet->LayoutType()), static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid));
|
||||
Assert::AreEqual(zoneSet->GetZones().size(), static_cast<size_t>(3));
|
||||
Assert::AreEqual(static_cast<int>(defaultLayout.type), static_cast<int>(zoneSet->LayoutType()));
|
||||
Assert::AreEqual(static_cast<size_t>(defaultLayout.zoneCount), zoneSet->GetZones().size());
|
||||
}
|
||||
|
||||
TEST_METHOD (CreateWorkAreaClonedFromParent)
|
||||
@@ -107,6 +108,67 @@ namespace FancyZonesUnitTests
|
||||
Assert::AreEqual(layout.spacing, actualLayout.spacing);
|
||||
Assert::AreEqual(layout.zoneCount, actualLayout.zoneCount);
|
||||
}
|
||||
|
||||
TEST_METHOD (CreateWorkAreaWithCustomDefault)
|
||||
{
|
||||
// prepare
|
||||
json::JsonObject root{};
|
||||
json::JsonArray layoutsArray{};
|
||||
json::JsonObject layout{};
|
||||
layout.SetNamedValue(NonLocalizable::DefaultLayoutsIds::UuidID, json::value(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}"));
|
||||
layout.SetNamedValue(NonLocalizable::DefaultLayoutsIds::TypeID, json::value(L"custom"));
|
||||
json::JsonObject item{};
|
||||
item.SetNamedValue(NonLocalizable::DefaultLayoutsIds::MonitorConfigurationTypeID, json::value(L"horizontal"));
|
||||
item.SetNamedValue(NonLocalizable::DefaultLayoutsIds::LayoutID, layout);
|
||||
layoutsArray.Append(item);
|
||||
root.SetNamedValue(NonLocalizable::DefaultLayoutsIds::DefaultLayoutsArrayID, layoutsArray);
|
||||
|
||||
json::to_file(DefaultLayouts::DefaultLayoutsFileName(), root);
|
||||
DefaultLayouts::instance().LoadData();
|
||||
|
||||
// test
|
||||
auto workArea = MakeWorkArea({}, Mocks::Monitor(), m_uniqueId, m_emptyUniqueId);
|
||||
Assert::IsFalse(workArea == nullptr);
|
||||
Assert::IsTrue(m_uniqueId == workArea->UniqueId());
|
||||
|
||||
auto* zoneSet{ workArea->ZoneSet() };
|
||||
Assert::IsNotNull(zoneSet);
|
||||
Assert::AreEqual(static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::Custom), static_cast<int>(zoneSet->LayoutType()));
|
||||
Assert::IsTrue(FancyZonesUtils::GuidFromString(L"{ACE817FD-2C51-4E13-903A-84CAB86FD17C}").value() == zoneSet->Id());
|
||||
}
|
||||
|
||||
TEST_METHOD (CreateWorkAreaWithTemplateDefault)
|
||||
{
|
||||
// prepare
|
||||
json::JsonObject root{};
|
||||
json::JsonArray layoutsArray{};
|
||||
json::JsonObject layout{};
|
||||
layout.SetNamedValue(NonLocalizable::DefaultLayoutsIds::TypeID, json::value(L"grid"));
|
||||
layout.SetNamedValue(NonLocalizable::DefaultLayoutsIds::ShowSpacingID, json::value(true));
|
||||
layout.SetNamedValue(NonLocalizable::DefaultLayoutsIds::SpacingID, json::value(1));
|
||||
layout.SetNamedValue(NonLocalizable::DefaultLayoutsIds::ZoneCountID, json::value(4));
|
||||
layout.SetNamedValue(NonLocalizable::DefaultLayoutsIds::SensitivityRadiusID, json::value(30));
|
||||
|
||||
json::JsonObject item{};
|
||||
item.SetNamedValue(NonLocalizable::DefaultLayoutsIds::MonitorConfigurationTypeID, json::value(L"horizontal"));
|
||||
item.SetNamedValue(NonLocalizable::DefaultLayoutsIds::LayoutID, layout);
|
||||
layoutsArray.Append(item);
|
||||
root.SetNamedValue(NonLocalizable::DefaultLayoutsIds::DefaultLayoutsArrayID, layoutsArray);
|
||||
|
||||
json::to_file(DefaultLayouts::DefaultLayoutsFileName(), root);
|
||||
DefaultLayouts::instance().LoadData();
|
||||
|
||||
// test
|
||||
auto workArea = MakeWorkArea({}, Mocks::Monitor(), m_uniqueId, m_emptyUniqueId);
|
||||
Assert::IsFalse(workArea == nullptr);
|
||||
Assert::IsTrue(m_uniqueId == workArea->UniqueId());
|
||||
|
||||
auto* zoneSet{ workArea->ZoneSet() };
|
||||
Assert::IsNotNull(zoneSet);
|
||||
Assert::AreEqual(static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::Grid), static_cast<int>(zoneSet->LayoutType()));
|
||||
Assert::AreEqual(static_cast<size_t>(4), zoneSet->GetZones().size());
|
||||
Assert::IsTrue(GUID_NULL == zoneSet->Id());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CLASS (WorkAreaUnitTests)
|
||||
|
||||
@@ -113,6 +113,13 @@ namespace FancyZonesEditor
|
||||
MessageBox.Show(parseResult.Message, FancyZonesEditor.Properties.Resources.Error_Parsing_Data_Title, MessageBoxButton.OK);
|
||||
}
|
||||
|
||||
parseResult = FancyZonesEditorIO.ParseDefaultLayouts();
|
||||
if (!parseResult.Result)
|
||||
{
|
||||
Logger.LogError(ParsingErrorReportTag + ": " + parseResult.Message + "; " + ParsingErrorDataTag + ": " + parseResult.MalformedData);
|
||||
MessageBox.Show(parseResult.Message, FancyZonesEditor.Properties.Resources.Error_Parsing_Data_Title, MessageBoxButton.OK);
|
||||
}
|
||||
|
||||
MainWindowSettingsModel settings = ((App)Current).MainWindowSettings;
|
||||
settings.UpdateSelectedLayoutModel();
|
||||
|
||||
|
||||
@@ -202,7 +202,7 @@
|
||||
FontWeight="SemiBold"
|
||||
FontSize="24" />
|
||||
|
||||
<ui:GridView ItemsSource="{Binding DefaultModels}"
|
||||
<ui:GridView ItemsSource="{Binding TemplateModels}"
|
||||
Grid.Row="1"
|
||||
ItemTemplate="{StaticResource LayoutItemTemplate}"
|
||||
AutomationProperties.LabeledBy="{Binding ElementName=TemplatesHeaderBlock}"
|
||||
@@ -589,9 +589,6 @@
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
|
||||
|
||||
|
||||
<StackPanel Margin="0, 12, 0, 0">
|
||||
<TextBlock Text="{x:Static props:Resources.Distance_adjacent_zones}"
|
||||
x:Name="distanceTitle"
|
||||
@@ -635,6 +632,97 @@
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="0,16,0,0"
|
||||
Visibility="{Binding Path=Type, Converter={StaticResource LayoutTypeTemplateToVisibilityConverter}}">
|
||||
|
||||
<TextBlock FontFamily="Segoe MDL2 Assets"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
Margin="0,16,0,0"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Number_of_zones}"
|
||||
ToolTip="{x:Static props:Resources.Number_of_zones}"
|
||||
Text="" />
|
||||
|
||||
<ui:NumberBox Minimum="1"
|
||||
Maximum="128"
|
||||
Width="216"
|
||||
KeyDown="EditDialogNumberBox_KeyDown"
|
||||
Margin="12,0,0,0"
|
||||
Header="{x:Static props:Resources.Number_of_zones}"
|
||||
Loaded="NumberBox_Loaded"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Number_of_zones}"
|
||||
SpinButtonPlacementMode="Compact"
|
||||
Text="{Binding TemplateZoneCount}" />
|
||||
</StackPanel>
|
||||
|
||||
|
||||
|
||||
<StackPanel Orientation="Vertical"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="0,16,0,0">
|
||||
|
||||
<Button x:Name="SetLayoutAsHorizontalDefaultButton"
|
||||
Click="SetLayoutAsHorizontalDefaultButton_Click"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Set_Layout_As_Horizontal_Default}"
|
||||
ToolTip="{x:Static props:Resources.Set_Layout_As_Horizontal_Default}"
|
||||
Style="{StaticResource IconOnlyButtonStyle}"
|
||||
Visibility="{Binding CanBeSetAsHorizontalDefault, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<Button.Content>
|
||||
<TextBlock AutomationProperties.Name="{x:Static props:Resources.Set_Layout_As_Horizontal_Default}"
|
||||
FontSize="14">
|
||||
<Run Text="" FontFamily="Segoe MDL2 Assets"/>
|
||||
<Run Text="{x:Static props:Resources.Default_Layout_Horizontal}"/>
|
||||
</TextBlock>
|
||||
</Button.Content>
|
||||
</Button>
|
||||
<Button x:Name="HorizontalDefaultLayoutButton"
|
||||
Click="HorizontalDefaultLayoutButton_Click"
|
||||
ToolTip="{x:Static props:Resources.Default_Layout_Horizontal}"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Default_Layout_Horizontal}"
|
||||
Style="{StaticResource IconOnlyButtonStyle}"
|
||||
Visibility="{Binding IsHorizontalDefault, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<Button.Content>
|
||||
<TextBlock AutomationProperties.Name="{x:Static props:Resources.Default_Layout_Horizontal}"
|
||||
FontSize="14">
|
||||
<Run Text="" FontFamily="Segoe MDL2 Assets"/>
|
||||
<Run Text="{x:Static props:Resources.Default_Layout_Horizontal}"/>
|
||||
</TextBlock>
|
||||
</Button.Content>
|
||||
</Button>
|
||||
|
||||
<Button x:Name="SetLayoutAsVerticalDefaultButton"
|
||||
Click="SetLayoutAsVerticalDefaultButton_Click"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Set_Layout_As_Vertical_Default}"
|
||||
ToolTip="{x:Static props:Resources.Set_Layout_As_Vertical_Default}"
|
||||
Style="{StaticResource IconOnlyButtonStyle}"
|
||||
Visibility="{Binding CanBeSetAsVerticalDefault, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<Button.Content>
|
||||
<TextBlock AutomationProperties.Name="{x:Static props:Resources.Set_Layout_As_Vertical_Default}"
|
||||
FontSize="14">
|
||||
<Run Text="" FontFamily="Segoe MDL2 Assets"/>
|
||||
<Run Text="{x:Static props:Resources.Default_Layout_Vertical}"/>
|
||||
</TextBlock>
|
||||
</Button.Content>
|
||||
</Button>
|
||||
<Button x:Name="VerticalDefaultLayoutButton"
|
||||
Click="VerticalDefaultLayoutButton_Click"
|
||||
ToolTip="{x:Static props:Resources.Default_Layout_Vertical}"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Default_Layout_Vertical}"
|
||||
Style="{StaticResource IconOnlyButtonStyle}"
|
||||
Visibility="{Binding IsVerticalDefault, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<Button.Content>
|
||||
<TextBlock AutomationProperties.Name="{x:Static props:Resources.Default_Layout_Vertical}"
|
||||
FontSize="14">
|
||||
<Run Text="" FontFamily="Segoe MDL2 Assets"/>
|
||||
<Run Text="{x:Static props:Resources.Default_Layout_Vertical}"/>
|
||||
</TextBlock>
|
||||
</Button.Content>
|
||||
</Button>
|
||||
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ui:ContentDialog>
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace FancyZonesEditor
|
||||
|
||||
private readonly MainWindowSettingsModel _settings = ((App)Application.Current).MainWindowSettings;
|
||||
private LayoutModel _backup;
|
||||
private List<LayoutModel> _defaultLayoutsBackup;
|
||||
|
||||
private ContentDialog _openedDialog;
|
||||
private TextBlock _createLayoutAnnounce;
|
||||
@@ -322,6 +323,8 @@ namespace FancyZonesEditor
|
||||
_backup = new CanvasLayoutModel(canvas);
|
||||
}
|
||||
|
||||
_defaultLayoutsBackup = new List<LayoutModel>(MainWindowSettingsModel.DefaultLayouts.DefaultLayouts);
|
||||
|
||||
Keyboard.ClearFocus();
|
||||
EditLayoutDialogTitle.Text = string.Format(CultureInfo.CurrentCulture, Properties.Resources.Edit_Template, ((LayoutModel)dataContext).Name);
|
||||
await EditLayoutDialog.ShowAsync();
|
||||
@@ -424,6 +427,7 @@ namespace FancyZonesEditor
|
||||
}
|
||||
|
||||
_backup = null;
|
||||
_defaultLayoutsBackup = null;
|
||||
|
||||
// update current settings
|
||||
if (model == _settings.AppliedModel)
|
||||
@@ -464,6 +468,8 @@ namespace FancyZonesEditor
|
||||
_backup = null;
|
||||
}
|
||||
|
||||
MainWindowSettingsModel.DefaultLayouts.Reset(model.Uuid);
|
||||
|
||||
if (model == _settings.AppliedModel)
|
||||
{
|
||||
_settings.SetAppliedModel(_settings.BlankModel);
|
||||
@@ -480,6 +486,7 @@ namespace FancyZonesEditor
|
||||
|
||||
App.FancyZonesEditorIO.SerializeAppliedLayouts();
|
||||
App.FancyZonesEditorIO.SerializeCustomLayouts();
|
||||
App.FancyZonesEditorIO.SerializeDefaultLayouts();
|
||||
model.Delete();
|
||||
}
|
||||
}
|
||||
@@ -543,6 +550,12 @@ namespace FancyZonesEditor
|
||||
_settings.RestoreSelectedModel(_backup);
|
||||
_backup = null;
|
||||
}
|
||||
|
||||
if (_defaultLayoutsBackup != null)
|
||||
{
|
||||
MainWindowSettingsModel.DefaultLayouts.Restore(_defaultLayoutsBackup);
|
||||
_defaultLayoutsBackup = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void NumberBox_Loaded(object sender, RoutedEventArgs e)
|
||||
@@ -586,5 +599,45 @@ namespace FancyZonesEditor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetLayoutAsVerticalDefaultButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dataContext = ((FrameworkElement)sender).DataContext;
|
||||
if (dataContext is LayoutModel model)
|
||||
{
|
||||
MainWindowSettingsModel.DefaultLayouts.Set(model, MonitorConfigurationType.Vertical);
|
||||
App.FancyZonesEditorIO.SerializeDefaultLayouts();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetLayoutAsHorizontalDefaultButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dataContext = ((FrameworkElement)sender).DataContext;
|
||||
if (dataContext is LayoutModel model)
|
||||
{
|
||||
MainWindowSettingsModel.DefaultLayouts.Set(model, MonitorConfigurationType.Horizontal);
|
||||
App.FancyZonesEditorIO.SerializeDefaultLayouts();
|
||||
}
|
||||
}
|
||||
|
||||
private void HorizontalDefaultLayoutButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dataContext = ((FrameworkElement)sender).DataContext;
|
||||
if (dataContext is LayoutModel model)
|
||||
{
|
||||
MainWindowSettingsModel.DefaultLayouts.Reset(MonitorConfigurationType.Horizontal);
|
||||
App.FancyZonesEditorIO.SerializeDefaultLayouts();
|
||||
}
|
||||
}
|
||||
|
||||
private void VerticalDefaultLayoutButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dataContext = ((FrameworkElement)sender).DataContext;
|
||||
if (dataContext is LayoutModel model)
|
||||
{
|
||||
MainWindowSettingsModel.DefaultLayouts.Reset(MonitorConfigurationType.Vertical);
|
||||
App.FancyZonesEditorIO.SerializeDefaultLayouts();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace FancyZonesEditor.Models
|
||||
{
|
||||
public class DefaultLayoutsModel : INotifyPropertyChanged
|
||||
{
|
||||
private static int Count { get; } = Enum.GetValues(typeof(MonitorConfigurationType)).Length;
|
||||
|
||||
public List<LayoutModel> DefaultLayouts { get; } = new List<LayoutModel>(Count);
|
||||
|
||||
public DefaultLayoutsModel()
|
||||
{
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public void Reset(MonitorConfigurationType type)
|
||||
{
|
||||
Set(MainWindowSettingsModel.TemplateModels[(int)LayoutType.PriorityGrid], type);
|
||||
}
|
||||
|
||||
public void Reset(string uuid)
|
||||
{
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
if (DefaultLayouts[i].Uuid == uuid)
|
||||
{
|
||||
Set(MainWindowSettingsModel.TemplateModels[(int)LayoutType.PriorityGrid], (MonitorConfigurationType)i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Set(LayoutModel layout, MonitorConfigurationType type)
|
||||
{
|
||||
if (DefaultLayouts.Count <= (int)type)
|
||||
{
|
||||
DefaultLayouts.Insert((int)type, layout);
|
||||
}
|
||||
else
|
||||
{
|
||||
DefaultLayouts[(int)type] = layout;
|
||||
}
|
||||
|
||||
FirePropertyChanged();
|
||||
}
|
||||
|
||||
public void Restore(List<LayoutModel> layouts)
|
||||
{
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
Set(layouts[i], (MonitorConfigurationType)i);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void FirePropertyChanged([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,8 @@ namespace FancyZonesEditor.Models
|
||||
{
|
||||
_guid = Guid.NewGuid();
|
||||
Type = LayoutType.Custom;
|
||||
|
||||
MainWindowSettingsModel.DefaultLayouts.PropertyChanged += DefaultLayouts_PropertyChanged;
|
||||
}
|
||||
|
||||
protected LayoutModel(string name)
|
||||
@@ -144,6 +146,38 @@ namespace FancyZonesEditor.Models
|
||||
|
||||
private bool _isApplied;
|
||||
|
||||
public bool IsHorizontalDefault
|
||||
{
|
||||
get
|
||||
{
|
||||
return MainWindowSettingsModel.DefaultLayouts.DefaultLayouts[(int)MonitorConfigurationType.Horizontal].Uuid == this.Uuid;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanBeSetAsHorizontalDefault
|
||||
{
|
||||
get
|
||||
{
|
||||
return MainWindowSettingsModel.DefaultLayouts.DefaultLayouts[(int)MonitorConfigurationType.Horizontal].Uuid != this.Uuid;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsVerticalDefault
|
||||
{
|
||||
get
|
||||
{
|
||||
return MainWindowSettingsModel.DefaultLayouts.DefaultLayouts[(int)MonitorConfigurationType.Vertical].Uuid == this.Uuid;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanBeSetAsVerticalDefault
|
||||
{
|
||||
get
|
||||
{
|
||||
return MainWindowSettingsModel.DefaultLayouts.DefaultLayouts[(int)MonitorConfigurationType.Vertical].Uuid != this.Uuid;
|
||||
}
|
||||
}
|
||||
|
||||
public int SensitivityRadius
|
||||
{
|
||||
get
|
||||
@@ -334,5 +368,13 @@ namespace FancyZonesEditor.Models
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DefaultLayouts_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
FirePropertyChanged(nameof(IsHorizontalDefault));
|
||||
FirePropertyChanged(nameof(IsVerticalDefault));
|
||||
FirePropertyChanged(nameof(CanBeSetAsHorizontalDefault));
|
||||
FirePropertyChanged(nameof(CanBeSetAsVerticalDefault));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,10 +23,6 @@ namespace FancyZonesEditor
|
||||
VirtualDesktopId,
|
||||
}
|
||||
|
||||
// Non-localizable strings
|
||||
public static readonly string RegistryPath = "SOFTWARE\\SuperFancyZones";
|
||||
public static readonly string FullRegistryPath = "HKEY_CURRENT_USER\\" + RegistryPath;
|
||||
|
||||
public bool IsCustomLayoutActive
|
||||
{
|
||||
get
|
||||
@@ -43,6 +39,8 @@ namespace FancyZonesEditor
|
||||
}
|
||||
}
|
||||
|
||||
public static DefaultLayoutsModel DefaultLayouts { get; } = new DefaultLayoutsModel();
|
||||
|
||||
public MainWindowSettingsModel()
|
||||
{
|
||||
// Initialize default layout models: Blank, Focus, Columns, Rows, Grid, and PriorityGrid
|
||||
@@ -51,11 +49,11 @@ namespace FancyZonesEditor
|
||||
TemplateZoneCount = 0,
|
||||
SensitivityRadius = 0,
|
||||
};
|
||||
DefaultModels.Insert((int)LayoutType.Blank, blankModel);
|
||||
TemplateModels.Insert((int)LayoutType.Blank, blankModel);
|
||||
|
||||
var focusModel = new CanvasLayoutModel(Properties.Resources.Template_Layout_Focus, LayoutType.Focus);
|
||||
focusModel.InitTemplateZones();
|
||||
DefaultModels.Insert((int)LayoutType.Focus, focusModel);
|
||||
TemplateModels.Insert((int)LayoutType.Focus, focusModel);
|
||||
|
||||
var columnsModel = new GridLayoutModel(Properties.Resources.Template_Layout_Columns, LayoutType.Columns)
|
||||
{
|
||||
@@ -63,7 +61,7 @@ namespace FancyZonesEditor
|
||||
RowPercents = new List<int>(1) { GridLayoutModel.GridMultiplier },
|
||||
};
|
||||
columnsModel.InitTemplateZones();
|
||||
DefaultModels.Insert((int)LayoutType.Columns, columnsModel);
|
||||
TemplateModels.Insert((int)LayoutType.Columns, columnsModel);
|
||||
|
||||
var rowsModel = new GridLayoutModel(Properties.Resources.Template_Layout_Rows, LayoutType.Rows)
|
||||
{
|
||||
@@ -71,15 +69,19 @@ namespace FancyZonesEditor
|
||||
ColumnPercents = new List<int>(1) { GridLayoutModel.GridMultiplier },
|
||||
};
|
||||
rowsModel.InitTemplateZones();
|
||||
DefaultModels.Insert((int)LayoutType.Rows, rowsModel);
|
||||
TemplateModels.Insert((int)LayoutType.Rows, rowsModel);
|
||||
|
||||
var gridModel = new GridLayoutModel(Properties.Resources.Template_Layout_Grid, LayoutType.Grid);
|
||||
gridModel.InitTemplateZones();
|
||||
DefaultModels.Insert((int)LayoutType.Grid, gridModel);
|
||||
TemplateModels.Insert((int)LayoutType.Grid, gridModel);
|
||||
|
||||
var priorityGridModel = new GridLayoutModel(Properties.Resources.Template_Layout_Priority_Grid, LayoutType.PriorityGrid);
|
||||
priorityGridModel.InitTemplateZones();
|
||||
DefaultModels.Insert((int)LayoutType.PriorityGrid, priorityGridModel);
|
||||
TemplateModels.Insert((int)LayoutType.PriorityGrid, priorityGridModel);
|
||||
|
||||
// set default layouts
|
||||
DefaultLayouts.Set(priorityGridModel, MonitorConfigurationType.Horizontal);
|
||||
DefaultLayouts.Set(priorityGridModel, MonitorConfigurationType.Vertical);
|
||||
}
|
||||
|
||||
// IsShiftKeyPressed - is the shift key currently being held down
|
||||
@@ -126,11 +128,11 @@ namespace FancyZonesEditor
|
||||
{
|
||||
get
|
||||
{
|
||||
return DefaultModels[(int)LayoutType.Blank];
|
||||
return TemplateModels[(int)LayoutType.Blank];
|
||||
}
|
||||
}
|
||||
|
||||
public static IList<LayoutModel> DefaultModels { get; } = new List<LayoutModel>(6);
|
||||
public static IList<LayoutModel> TemplateModels { get; } = new List<LayoutModel>(6);
|
||||
|
||||
public static ObservableCollection<LayoutModel> CustomModels
|
||||
{
|
||||
@@ -213,7 +215,7 @@ namespace FancyZonesEditor
|
||||
|
||||
public void InitModels()
|
||||
{
|
||||
foreach (var model in DefaultModels)
|
||||
foreach (var model in TemplateModels)
|
||||
{
|
||||
model.InitTemplateZones();
|
||||
}
|
||||
@@ -239,7 +241,7 @@ namespace FancyZonesEditor
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (LayoutModel model in DefaultModels)
|
||||
foreach (LayoutModel model in TemplateModels)
|
||||
{
|
||||
if (model.Type == currentApplied.Type)
|
||||
{
|
||||
@@ -261,7 +263,7 @@ namespace FancyZonesEditor
|
||||
|
||||
if (foundModel == null)
|
||||
{
|
||||
foundModel = DefaultModels[(int)LayoutType.PriorityGrid];
|
||||
foundModel = TemplateModels[(int)LayoutType.PriorityGrid];
|
||||
}
|
||||
|
||||
SetSelectedModel(foundModel);
|
||||
@@ -321,9 +323,9 @@ namespace FancyZonesEditor
|
||||
AppliedModel = model;
|
||||
}
|
||||
|
||||
public void UpdateDefaultModels()
|
||||
public void UpdateTemplateModels()
|
||||
{
|
||||
foreach (LayoutModel model in DefaultModels)
|
||||
foreach (LayoutModel model in TemplateModels)
|
||||
{
|
||||
if (App.Overlay.CurrentLayoutSettings.Type == model.Type && App.Overlay.CurrentLayoutSettings.ZoneCount != model.TemplateZoneCount)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace FancyZonesEditor.Models
|
||||
{
|
||||
public enum MonitorConfigurationType
|
||||
{
|
||||
Horizontal = 0,
|
||||
Vertical,
|
||||
}
|
||||
}
|
||||
@@ -107,7 +107,7 @@ namespace FancyZonesEditor
|
||||
if (settings != null)
|
||||
{
|
||||
settings.SetAppliedModel(null);
|
||||
settings.UpdateDefaultModels();
|
||||
settings.UpdateTemplateModels();
|
||||
}
|
||||
|
||||
Update();
|
||||
|
||||
@@ -222,6 +222,24 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Default layout for horizontal monitor orientation.
|
||||
/// </summary>
|
||||
public static string Default_Layout_Horizontal {
|
||||
get {
|
||||
return ResourceManager.GetString("Default_Layout_Horizontal", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Default layout for vertical monitor orientation.
|
||||
/// </summary>
|
||||
public static string Default_Layout_Vertical {
|
||||
get {
|
||||
return ResourceManager.GetString("Default_Layout_Vertical", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Delete.
|
||||
/// </summary>
|
||||
@@ -451,6 +469,15 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to An error occurred while parsing default layouts..
|
||||
/// </summary>
|
||||
public static string Error_Parsing_Default_Layouts_Message {
|
||||
get {
|
||||
return ResourceManager.GetString("Error_Parsing_Default_Layouts_Message", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Error parsing device info data..
|
||||
/// </summary>
|
||||
@@ -762,6 +789,24 @@ namespace FancyZonesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Set layout as a default for horizontal monitor orientation.
|
||||
/// </summary>
|
||||
public static string Set_Layout_As_Horizontal_Default {
|
||||
get {
|
||||
return ResourceManager.GetString("Set_Layout_As_Horizontal_Default", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Set layout as a default for vertical monitor orientation.
|
||||
/// </summary>
|
||||
public static string Set_Layout_As_Vertical_Default {
|
||||
get {
|
||||
return ResourceManager.GetString("Set_Layout_As_Vertical_Default", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Template settings.
|
||||
/// </summary>
|
||||
|
||||
@@ -414,4 +414,19 @@
|
||||
<data name="Slider_Value" xml:space="preserve">
|
||||
<value>{0} pixels</value>
|
||||
</data>
|
||||
<data name="Default_Layout_Horizontal" xml:space="preserve">
|
||||
<value>Default layout for horizontal monitor orientation</value>
|
||||
</data>
|
||||
<data name="Set_Layout_As_Horizontal_Default" xml:space="preserve">
|
||||
<value>Set layout as a default for horizontal monitor orientation</value>
|
||||
</data>
|
||||
<data name="Error_Parsing_Default_Layouts_Message" xml:space="preserve">
|
||||
<value>An error occurred while parsing default layouts.</value>
|
||||
</data>
|
||||
<data name="Default_Layout_Vertical" xml:space="preserve">
|
||||
<value>Default layout for vertical monitor orientation</value>
|
||||
</data>
|
||||
<data name="Set_Layout_As_Vertical_Default" xml:space="preserve">
|
||||
<value>Set layout as a default for vertical monitor orientation</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -27,12 +27,15 @@ namespace FancyZonesEditor.Utils
|
||||
private const string GridJsonTag = "grid";
|
||||
private const string PriorityGridJsonTag = "priority-grid";
|
||||
private const string CustomJsonTag = "custom";
|
||||
private const string HorizontalJsonTag = "horizontal";
|
||||
private const string VerticalJsonTag = "vertical";
|
||||
|
||||
// Non-localizable strings: Files
|
||||
private const string AppliedLayoutsFile = "\\Microsoft\\PowerToys\\FancyZones\\applied-layouts.json";
|
||||
private const string LayoutHotkeysFile = "\\Microsoft\\PowerToys\\FancyZones\\layout-hotkeys.json";
|
||||
private const string LayoutTemplatesFile = "\\Microsoft\\PowerToys\\FancyZones\\layout-templates.json";
|
||||
private const string CustomLayoutsFile = "\\Microsoft\\PowerToys\\FancyZones\\custom-layouts.json";
|
||||
private const string DefaultLayoutsFile = "\\Microsoft\\PowerToys\\FancyZones\\default-layouts.json";
|
||||
private const string ParamsFile = "\\Microsoft\\PowerToys\\FancyZones\\editor-parameters.json";
|
||||
|
||||
// Non-localizable string: default virtual desktop id
|
||||
@@ -56,6 +59,8 @@ namespace FancyZonesEditor.Utils
|
||||
|
||||
public string FancyZonesCustomLayoutsFile { get; private set; }
|
||||
|
||||
public string FancyZonesDefaultLayoutsFile { get; private set; }
|
||||
|
||||
public string FancyZonesEditorParamsFile { get; private set; }
|
||||
|
||||
private enum CmdArgs
|
||||
@@ -264,6 +269,35 @@ namespace FancyZonesEditor.Utils
|
||||
public List<LayoutHotkeyWrapper> LayoutHotkeys { get; set; }
|
||||
}
|
||||
|
||||
// default-layouts.json
|
||||
private struct DefaultLayoutWrapper
|
||||
{
|
||||
public struct LayoutWrapper
|
||||
{
|
||||
public string Uuid { get; set; }
|
||||
|
||||
public string Type { get; set; }
|
||||
|
||||
public bool ShowSpacing { get; set; }
|
||||
|
||||
public int Spacing { get; set; }
|
||||
|
||||
public int ZoneCount { get; set; }
|
||||
|
||||
public int SensitivityRadius { get; set; }
|
||||
}
|
||||
|
||||
public string MonitorConfiguration { get; set; }
|
||||
|
||||
public LayoutWrapper Layout { get; set; }
|
||||
}
|
||||
|
||||
// default-layouts.json
|
||||
private struct DefaultLayoutsListWrapper
|
||||
{
|
||||
public List<DefaultLayoutWrapper> DefaultLayouts { get; set; }
|
||||
}
|
||||
|
||||
private struct EditorParams
|
||||
{
|
||||
public int ProcessId { get; set; }
|
||||
@@ -296,6 +330,7 @@ namespace FancyZonesEditor.Utils
|
||||
FancyZonesLayoutHotkeysFile = localAppDataDir + LayoutHotkeysFile;
|
||||
FancyZonesLayoutTemplatesFile = localAppDataDir + LayoutTemplatesFile;
|
||||
FancyZonesCustomLayoutsFile = localAppDataDir + CustomLayoutsFile;
|
||||
FancyZonesDefaultLayoutsFile = localAppDataDir + DefaultLayoutsFile;
|
||||
FancyZonesEditorParamsFile = localAppDataDir + ParamsFile;
|
||||
}
|
||||
|
||||
@@ -558,6 +593,46 @@ namespace FancyZonesEditor.Utils
|
||||
return new ParsingResult(true);
|
||||
}
|
||||
|
||||
public ParsingResult ParseDefaultLayouts()
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
if (_fileSystem.File.Exists(FancyZonesDefaultLayoutsFile))
|
||||
{
|
||||
DefaultLayoutsListWrapper wrapper;
|
||||
string dataString = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
dataString = ReadFile(FancyZonesDefaultLayoutsFile);
|
||||
wrapper = JsonSerializer.Deserialize<DefaultLayoutsListWrapper>(dataString, _options);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Default layouts parsing error", ex);
|
||||
return new ParsingResult(false, ex.Message, dataString);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
bool parsingResult = SetDefaultLayouts(wrapper.DefaultLayouts);
|
||||
if (parsingResult)
|
||||
{
|
||||
return new ParsingResult(true);
|
||||
}
|
||||
|
||||
return new ParsingResult(false, FancyZonesEditor.Properties.Resources.Error_Parsing_Default_Layouts_Message, dataString);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Default layouts parsing error", ex);
|
||||
return new ParsingResult(false, ex.Message, dataString);
|
||||
}
|
||||
}
|
||||
|
||||
return new ParsingResult(true);
|
||||
}
|
||||
|
||||
public void SerializeAppliedLayouts()
|
||||
{
|
||||
Logger.LogTrace();
|
||||
@@ -658,7 +733,7 @@ namespace FancyZonesEditor.Utils
|
||||
TemplateLayoutsListWrapper templates = new TemplateLayoutsListWrapper { };
|
||||
templates.LayoutTemplates = new List<TemplateLayoutWrapper>();
|
||||
|
||||
foreach (LayoutModel layout in MainWindowSettingsModel.DefaultModels)
|
||||
foreach (LayoutModel layout in MainWindowSettingsModel.TemplateModels)
|
||||
{
|
||||
TemplateLayoutWrapper wrapper = new TemplateLayoutWrapper
|
||||
{
|
||||
@@ -790,6 +865,107 @@ namespace FancyZonesEditor.Utils
|
||||
}
|
||||
}
|
||||
|
||||
public void SerializeDefaultLayouts()
|
||||
{
|
||||
DefaultLayoutsListWrapper layouts = new DefaultLayoutsListWrapper { };
|
||||
layouts.DefaultLayouts = new List<DefaultLayoutWrapper>();
|
||||
|
||||
foreach (LayoutModel layout in MainWindowSettingsModel.TemplateModels)
|
||||
{
|
||||
if (layout.IsHorizontalDefault || layout.IsVerticalDefault)
|
||||
{
|
||||
DefaultLayoutWrapper.LayoutWrapper layoutWrapper = new DefaultLayoutWrapper.LayoutWrapper
|
||||
{
|
||||
Uuid = string.Empty,
|
||||
Type = LayoutTypeToJsonTag(layout.Type),
|
||||
SensitivityRadius = layout.SensitivityRadius,
|
||||
ZoneCount = layout.TemplateZoneCount,
|
||||
};
|
||||
|
||||
if (layout is GridLayoutModel grid)
|
||||
{
|
||||
layoutWrapper.ShowSpacing = grid.ShowSpacing;
|
||||
layoutWrapper.Spacing = grid.Spacing;
|
||||
}
|
||||
|
||||
// can be both horizontal and vertical, so check separately
|
||||
if (layout.IsHorizontalDefault)
|
||||
{
|
||||
DefaultLayoutWrapper wrapper = new DefaultLayoutWrapper
|
||||
{
|
||||
MonitorConfiguration = MonitorConfigurationTypeToJsonTag(MonitorConfigurationType.Horizontal),
|
||||
Layout = layoutWrapper,
|
||||
};
|
||||
|
||||
layouts.DefaultLayouts.Add(wrapper);
|
||||
}
|
||||
|
||||
if (layout.IsVerticalDefault)
|
||||
{
|
||||
DefaultLayoutWrapper wrapper = new DefaultLayoutWrapper
|
||||
{
|
||||
MonitorConfiguration = MonitorConfigurationTypeToJsonTag(MonitorConfigurationType.Vertical),
|
||||
Layout = layoutWrapper,
|
||||
};
|
||||
|
||||
layouts.DefaultLayouts.Add(wrapper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (LayoutModel layout in MainWindowSettingsModel.CustomModels)
|
||||
{
|
||||
if (layout.IsHorizontalDefault || layout.IsVerticalDefault)
|
||||
{
|
||||
DefaultLayoutWrapper.LayoutWrapper layoutWrapper = new DefaultLayoutWrapper.LayoutWrapper
|
||||
{
|
||||
Uuid = layout.Uuid,
|
||||
Type = LayoutTypeToJsonTag(LayoutType.Custom),
|
||||
};
|
||||
|
||||
if (layout is GridLayoutModel grid)
|
||||
{
|
||||
layoutWrapper.ShowSpacing = grid.ShowSpacing;
|
||||
layoutWrapper.Spacing = grid.Spacing;
|
||||
}
|
||||
|
||||
// can be both horizontal and vertical, so check separately
|
||||
if (layout.IsHorizontalDefault)
|
||||
{
|
||||
DefaultLayoutWrapper wrapper = new DefaultLayoutWrapper
|
||||
{
|
||||
MonitorConfiguration = MonitorConfigurationTypeToJsonTag(MonitorConfigurationType.Horizontal),
|
||||
Layout = layoutWrapper,
|
||||
};
|
||||
|
||||
layouts.DefaultLayouts.Add(wrapper);
|
||||
}
|
||||
|
||||
if (layout.IsVerticalDefault)
|
||||
{
|
||||
DefaultLayoutWrapper wrapper = new DefaultLayoutWrapper
|
||||
{
|
||||
MonitorConfiguration = MonitorConfigurationTypeToJsonTag(MonitorConfigurationType.Vertical),
|
||||
Layout = layoutWrapper,
|
||||
};
|
||||
|
||||
layouts.DefaultLayouts.Add(wrapper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string jsonString = JsonSerializer.Serialize(layouts, _options);
|
||||
_fileSystem.File.WriteAllText(FancyZonesDefaultLayoutsFile, jsonString);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Serialize default layout error", ex);
|
||||
App.ShowExceptionMessageBox(Properties.Resources.Error_Applying_Layout, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private string ReadFile(string fileName)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
@@ -942,7 +1118,7 @@ namespace FancyZonesEditor.Utils
|
||||
foreach (var wrapper in templateLayouts)
|
||||
{
|
||||
LayoutType type = JsonTagToLayoutType(wrapper.Type);
|
||||
LayoutModel layout = MainWindowSettingsModel.DefaultModels[(int)type];
|
||||
LayoutModel layout = MainWindowSettingsModel.TemplateModels[(int)type];
|
||||
|
||||
layout.SensitivityRadius = wrapper.SensitivityRadius;
|
||||
layout.TemplateZoneCount = wrapper.ZoneCount;
|
||||
@@ -972,6 +1148,41 @@ namespace FancyZonesEditor.Utils
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool SetDefaultLayouts(List<DefaultLayoutWrapper> layouts)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
if (layouts == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var layout in layouts)
|
||||
{
|
||||
if (layout.Layout.Uuid != null && layout.Layout.Uuid != string.Empty)
|
||||
{
|
||||
MonitorConfigurationType type = JsonTagToMonitorConfigurationType(layout.MonitorConfiguration);
|
||||
|
||||
foreach (var customLayout in MainWindowSettingsModel.CustomModels)
|
||||
{
|
||||
if (customLayout.Uuid == layout.Layout.Uuid)
|
||||
{
|
||||
MainWindowSettingsModel.DefaultLayouts.Set(customLayout, type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LayoutType layoutType = JsonTagToLayoutType(layout.Layout.Type);
|
||||
MonitorConfigurationType type = JsonTagToMonitorConfigurationType(layout.MonitorConfiguration);
|
||||
MainWindowSettingsModel.DefaultLayouts.Set(MainWindowSettingsModel.TemplateModels[(int)layoutType], type);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private CanvasLayoutModel ParseCanvasInfo(CustomLayoutWrapper wrapper)
|
||||
{
|
||||
var info = JsonSerializer.Deserialize<CanvasInfoWrapper>(wrapper.Info.GetRawText(), _options);
|
||||
@@ -1089,5 +1300,31 @@ namespace FancyZonesEditor.Utils
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
private MonitorConfigurationType JsonTagToMonitorConfigurationType(string tag)
|
||||
{
|
||||
switch (tag)
|
||||
{
|
||||
case HorizontalJsonTag:
|
||||
return MonitorConfigurationType.Horizontal;
|
||||
case VerticalJsonTag:
|
||||
return MonitorConfigurationType.Vertical;
|
||||
}
|
||||
|
||||
return MonitorConfigurationType.Horizontal;
|
||||
}
|
||||
|
||||
private string MonitorConfigurationTypeToJsonTag(MonitorConfigurationType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MonitorConfigurationType.Horizontal:
|
||||
return HorizontalJsonTag;
|
||||
case MonitorConfigurationType.Vertical:
|
||||
return VerticalJsonTag;
|
||||
}
|
||||
|
||||
return HorizontalJsonTag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user