mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-05 18:57:19 +02:00
[FancyZones Editor] New UX for the FZ editor. (#9325)
* Removed MetroWindow, added theming support and modernWPF * Rmoved MahApps refs * Removed MahApps * Updated canvas zones * Updated GridEditor * Fixes * UI updates * New layout type selection dialog * New editor UI * Updates * Fix * UI enhancements * Updated UI * Added styles to layoutpreview * Accesibility improvements * Accesibility and styling improvements * Fix * Cleaned up brushes * Updated UX * Updated UI * Added no layouts description * Fix * UI fixes * [FZ Editor] Serialize/deserialize settings (#8615) * conflicts fix * [FZ Editor] Parse json file instead of command line args (#8649) * [FZ Editor] Serialize/deserialize settings fix (#8707) * [FZ Editor] Hide unsupported settings in custom layouts flyouts (#8716) * [FZ Editor] Duplicate custom layouts (#8718) * [FZ Editor] Duplicate layout behavior (#8720) * New UX proposal * Updated spacing * Switching to toggleswitches * Revert toggleswitch * Updated colorbrush * Updated string for saving label * Updated UI * Dark theme color fixes * Removed space * [FZ Editor] Bind dialog properties (#9199) * Resize editor window to fit the content in single-monitor mode (#9203) * Editor opening fix (#9207) * Disable "Create" button if the Name textbox is empty (#9212) * [FZ Editor] Changed edit dialog for template layouts. (#9233) * [FZ Editor] Small fixes and refactoring. (#9236) * new layout creation refactoring * "Save and apply" applies the layout * number of zones header hide * [FZ Editor] Empty layout template. (#9237) * [FZ Editor] Move "Duplicate" and "Delete" buttons to the Edit dialog. (#9272) * [FZ Editor] Preview the applied layout after editing another layout. (#9278) * Fixed "Save and apply" button behavior (#9286) * [FZ Editor] Save template layouts in the settings. (#9283) * Added default custom layout name (#9291) * close dialog before opening zones editor (#9302) * Pressing Esc closes dialogs (#9301) * [FZ Editor] Reset applied layout to "No layout" if it was deleted. (#9315) * [FZ Editor] Dark theme colors (#9317) * "Number of zones" buttons colors. (#9321) * rebase fix * added ModernWpf.dll * address PR comments: updated colors * added comments, replaced magic numbers * refactoring * merge zones crash fix * removed redundant using directive Co-authored-by: Niels Laute <niels9001@hotmail.com> Co-authored-by: Niels Laute <niels.laute@live.nl>
This commit is contained in:
@@ -17,16 +17,13 @@
|
||||
namespace NonLocalizable
|
||||
{
|
||||
const wchar_t ActiveZoneSetStr[] = L"active-zoneset";
|
||||
const wchar_t AppliedZonesets[] = L"applied-zonesets";
|
||||
const wchar_t AppPathStr[] = L"app-path";
|
||||
const wchar_t AppZoneHistoryStr[] = L"app-zone-history";
|
||||
const wchar_t CanvasStr[] = L"canvas";
|
||||
const wchar_t CellChildMapStr[] = L"cell-child-map";
|
||||
const wchar_t ColumnsPercentageStr[] = L"columns-percentage";
|
||||
const wchar_t ColumnsStr[] = L"columns";
|
||||
const wchar_t CreatedCustomZoneSets[] = L"created-custom-zone-sets";
|
||||
const wchar_t CustomZoneSetsStr[] = L"custom-zone-sets";
|
||||
const wchar_t DeletedCustomZoneSetsStr[] = L"deleted-custom-zone-sets";
|
||||
const wchar_t DeviceIdStr[] = L"device-id";
|
||||
const wchar_t DevicesStr[] = L"devices";
|
||||
const wchar_t EditorShowSpacingStr[] = L"editor-show-spacing";
|
||||
@@ -42,6 +39,10 @@ namespace NonLocalizable
|
||||
const wchar_t RefWidthStr[] = L"ref-width";
|
||||
const wchar_t RowsPercentageStr[] = L"rows-percentage";
|
||||
const wchar_t RowsStr[] = L"rows";
|
||||
const wchar_t SensitivityRadius[] = L"sensitivity-radius";
|
||||
const wchar_t ShowSpacing[] = L"show-spacing";
|
||||
const wchar_t Spacing[] = L"spacing";
|
||||
const wchar_t Templates[] = L"templates";
|
||||
const wchar_t TypeStr[] = L"type";
|
||||
const wchar_t UuidStr[] = L"uuid";
|
||||
const wchar_t WidthStr[] = L"width";
|
||||
@@ -51,6 +52,16 @@ namespace NonLocalizable
|
||||
const wchar_t ZoneIndexStr[] = L"zone-index";
|
||||
const wchar_t ZoneSetUuidStr[] = L"zoneset-uuid";
|
||||
const wchar_t ZonesStr[] = L"zones";
|
||||
|
||||
// Editor arguments
|
||||
const wchar_t Dpi[] = L"dpi";
|
||||
const wchar_t MonitorId[] = L"monitor-id";
|
||||
const wchar_t TopCoordinate[] = L"top-coordinate";
|
||||
const wchar_t LeftCoordinate[] = L"left-coordinate";
|
||||
const wchar_t IsSelected[] = L"is-selected";
|
||||
const wchar_t ProcessId[] = L"process-id";
|
||||
const wchar_t SpanZonesAcrossMonitors[] = L"span-zones-across-monitors";
|
||||
const wchar_t Monitors[] = L"monitors";
|
||||
}
|
||||
|
||||
namespace
|
||||
@@ -130,6 +141,7 @@ namespace JSONHelpers
|
||||
zonesJson.Append(zoneJson);
|
||||
}
|
||||
infoJson.SetNamedValue(NonLocalizable::ZonesStr, zonesJson);
|
||||
infoJson.SetNamedValue(NonLocalizable::SensitivityRadius, json::value(canvasInfo.sensitivityRadius));
|
||||
return infoJson;
|
||||
}
|
||||
|
||||
@@ -154,6 +166,8 @@ namespace JSONHelpers
|
||||
FancyZonesDataTypes::CanvasLayoutInfo::Rect zone{ x, y, width, height };
|
||||
info.zones.push_back(zone);
|
||||
}
|
||||
|
||||
info.sensitivityRadius = static_cast<int>(infoJson.GetNamedNumber(NonLocalizable::SensitivityRadius, DefaultValues::SensitivityRadius));
|
||||
return info;
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
@@ -176,6 +190,10 @@ namespace JSONHelpers
|
||||
cellChildMapJson.Append(NumVecToJsonArray(gridInfo.m_cellChildMap[i]));
|
||||
}
|
||||
infoJson.SetNamedValue(NonLocalizable::CellChildMapStr, cellChildMapJson);
|
||||
|
||||
infoJson.SetNamedValue(NonLocalizable::SensitivityRadius, json::value(gridInfo.m_sensitivityRadius));
|
||||
infoJson.SetNamedValue(NonLocalizable::ShowSpacing, json::value(gridInfo.m_showSpacing));
|
||||
infoJson.SetNamedValue(NonLocalizable::Spacing, json::value(gridInfo.m_spacing));
|
||||
|
||||
return infoJson;
|
||||
}
|
||||
@@ -210,6 +228,10 @@ namespace JSONHelpers
|
||||
info.cellChildMap().push_back(JsonArrayToNumVec(cellsArray));
|
||||
}
|
||||
|
||||
info.m_showSpacing = infoJson.GetNamedBoolean(NonLocalizable::ShowSpacing, DefaultValues::ShowSpacing);
|
||||
info.m_spacing = static_cast<int>(infoJson.GetNamedNumber(NonLocalizable::Spacing, DefaultValues::Spacing));
|
||||
info.m_sensitivityRadius = static_cast<int>(infoJson.GetNamedNumber(NonLocalizable::SensitivityRadius, DefaultValues::SensitivityRadius));
|
||||
|
||||
return info;
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
@@ -449,64 +471,37 @@ namespace JSONHelpers
|
||||
}
|
||||
}
|
||||
|
||||
json::JsonObject AppliedZonesetsJSON::ToJson(const TDeviceInfoMap& deviceInfoMap)
|
||||
json::JsonObject MonitorInfo::ToJson(const MonitorInfo& monitor)
|
||||
{
|
||||
json::JsonObject result{};
|
||||
|
||||
json::JsonArray array;
|
||||
for (const auto& info : deviceInfoMap)
|
||||
{
|
||||
JSONHelpers::DeviceInfoJSON deviceInfoJson{ info.first, info.second };
|
||||
array.Append(JSONHelpers::DeviceInfoJSON::ToJson(deviceInfoJson));
|
||||
}
|
||||
result.SetNamedValue(NonLocalizable::Dpi, json::value(monitor.dpi));
|
||||
result.SetNamedValue(NonLocalizable::MonitorId, json::value(monitor.id));
|
||||
result.SetNamedValue(NonLocalizable::TopCoordinate, json::value(monitor.top));
|
||||
result.SetNamedValue(NonLocalizable::LeftCoordinate, json::value(monitor.left));
|
||||
result.SetNamedValue(NonLocalizable::IsSelected, json::value(monitor.isSelected));
|
||||
|
||||
result.SetNamedValue(NonLocalizable::AppliedZonesets, array);
|
||||
return result;
|
||||
}
|
||||
|
||||
json::JsonObject AppliedZonesetsJSON::ToJson(const TDeviceInfoMap& deviceInfoMap, const GUID& currentVirtualDesktop)
|
||||
json::JsonObject EditorArgs::ToJson(const EditorArgs& args)
|
||||
{
|
||||
json::JsonObject result{};
|
||||
|
||||
json::JsonArray array;
|
||||
for (const auto& info : deviceInfoMap)
|
||||
result.SetNamedValue(NonLocalizable::ProcessId, json::value(args.processId));
|
||||
result.SetNamedValue(NonLocalizable::SpanZonesAcrossMonitors, json::value(args.spanZonesAcrossMonitors));
|
||||
|
||||
json::JsonArray monitors;
|
||||
for (const auto& monitor : args.monitors)
|
||||
{
|
||||
std::optional<FancyZonesDataTypes::DeviceIdData> id = FancyZonesUtils::ParseDeviceId(info.first);
|
||||
if (id.has_value() && id->virtualDesktopId == currentVirtualDesktop)
|
||||
{
|
||||
JSONHelpers::DeviceInfoJSON deviceInfoJson{ info.first, info.second };
|
||||
array.Append(JSONHelpers::DeviceInfoJSON::ToJson(deviceInfoJson));
|
||||
}
|
||||
monitors.Append(MonitorInfo::ToJson(monitor));
|
||||
}
|
||||
|
||||
result.SetNamedValue(NonLocalizable::AppliedZonesets, array);
|
||||
result.SetNamedValue(NonLocalizable::Monitors, monitors);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::optional<TDeviceInfoMap> AppliedZonesetsJSON::FromJson(const json::JsonObject& json)
|
||||
{
|
||||
try
|
||||
{
|
||||
TDeviceInfoMap appliedZonesets;
|
||||
|
||||
auto zonesets = json.GetNamedArray(NonLocalizable::AppliedZonesets);
|
||||
for (const auto& zoneset : zonesets)
|
||||
{
|
||||
std::optional<DeviceInfoJSON> device = DeviceInfoJSON::FromJson(zoneset.GetObjectW());
|
||||
if (device.has_value())
|
||||
{
|
||||
appliedZonesets.insert(std::make_pair(device->deviceId, device->data));
|
||||
}
|
||||
}
|
||||
|
||||
return appliedZonesets;
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
json::JsonObject GetPersistFancyZonesJSON(const std::wstring& zonesSettingsFileName, const std::wstring& appZoneHistoryFileName)
|
||||
{
|
||||
auto result = json::from_file(zonesSettingsFileName);
|
||||
@@ -534,12 +529,27 @@ namespace JSONHelpers
|
||||
|
||||
void SaveZoneSettings(const std::wstring& zonesSettingsFileName, const TDeviceInfoMap& deviceInfoMap, const TCustomZoneSetsMap& customZoneSetsMap)
|
||||
{
|
||||
json::JsonObject root{};
|
||||
auto before = json::from_file(zonesSettingsFileName);
|
||||
|
||||
json::JsonObject root{};
|
||||
json::JsonArray templates{};
|
||||
|
||||
try
|
||||
{
|
||||
if (before.has_value() && before->HasKey(NonLocalizable::Templates))
|
||||
{
|
||||
templates = before->GetNamedArray(NonLocalizable::Templates);
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
root.SetNamedValue(NonLocalizable::DevicesStr, JSONHelpers::SerializeDeviceInfos(deviceInfoMap));
|
||||
root.SetNamedValue(NonLocalizable::CustomZoneSetsStr, JSONHelpers::SerializeCustomZoneSets(customZoneSetsMap));
|
||||
|
||||
auto before = json::from_file(zonesSettingsFileName);
|
||||
root.SetNamedValue(NonLocalizable::Templates, templates);
|
||||
|
||||
if (!before.has_value() || before.value().Stringify() != root.Stringify())
|
||||
{
|
||||
Trace::FancyZones::DataChanged();
|
||||
@@ -665,104 +675,4 @@ namespace JSONHelpers
|
||||
|
||||
return customZoneSetsJSON;
|
||||
}
|
||||
|
||||
void SerializeDeviceInfoToTmpFile(const TDeviceInfoMap& deviceInfoMap, const GUID& currentVirtualDesktop, std::wstring_view tmpFilePath)
|
||||
{
|
||||
json::to_file(tmpFilePath, JSONHelpers::AppliedZonesetsJSON::ToJson(deviceInfoMap, currentVirtualDesktop));
|
||||
}
|
||||
|
||||
void SerializeCustomZoneSetsToTmpFile(const TCustomZoneSetsMap& customZoneSetsMap, std::wstring_view tmpFilePath)
|
||||
{
|
||||
json::JsonObject result{};
|
||||
|
||||
json::JsonArray array;
|
||||
for (const auto& zoneSet : customZoneSetsMap)
|
||||
{
|
||||
CustomZoneSetJSON json{ zoneSet.first, zoneSet.second };
|
||||
array.Append(JSONHelpers::CustomZoneSetJSON::ToJson(json));
|
||||
}
|
||||
|
||||
result.SetNamedValue(NonLocalizable::CreatedCustomZoneSets, array);
|
||||
json::to_file(tmpFilePath, result);
|
||||
}
|
||||
|
||||
std::optional<TDeviceInfoMap> ParseDeviceInfoFromTmpFile(std::wstring_view tmpFilePath)
|
||||
{
|
||||
std::optional<TDeviceInfoMap> result{ std::nullopt };
|
||||
if (std::filesystem::exists(tmpFilePath))
|
||||
{
|
||||
if (auto zoneSetJson = json::from_file(tmpFilePath); zoneSetJson.has_value())
|
||||
{
|
||||
if (auto deviceInfo = JSONHelpers::AppliedZonesetsJSON::FromJson(zoneSetJson.value()); deviceInfo.has_value())
|
||||
{
|
||||
result = std::move(deviceInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::trace(L"ParseDeviceInfoFromTmpFile: AppliedZonesetsJSON::FromJson parsing error, {}", zoneSetJson.value().Stringify());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DeleteTmpFile(tmpFilePath);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<CustomZoneSetJSON> ParseCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath)
|
||||
{
|
||||
std::vector<CustomZoneSetJSON> result;
|
||||
if (std::filesystem::exists(tmpFilePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (auto customZoneSetJson = json::from_file(tmpFilePath); customZoneSetJson.has_value())
|
||||
{
|
||||
auto zoneSetArray = customZoneSetJson.value().GetNamedArray(NonLocalizable::CreatedCustomZoneSets);
|
||||
for (const auto& zoneSet : zoneSetArray)
|
||||
{
|
||||
if (auto customZoneSet = JSONHelpers::CustomZoneSetJSON::FromJson(zoneSet.GetObjectW()); customZoneSet.has_value())
|
||||
{
|
||||
result.emplace_back(std::move(*customZoneSet));
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::trace(L"ParseCustomZoneSetsFromTmpFile: CustomZoneSetJSON::FromJson parsing error, {}", zoneSet.GetObjectW().Stringify());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error& err)
|
||||
{
|
||||
Logger::trace(L"ParseCustomZoneSetsFromTmpFile: CustomZoneSetJSON::FromJson parsing error, {}", err.message());
|
||||
}
|
||||
|
||||
DeleteTmpFile(tmpFilePath);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::wstring> ParseDeletedCustomZoneSetsFromTmpFile(std::wstring_view tmpFilePath)
|
||||
{
|
||||
std::vector<std::wstring> result{};
|
||||
if (std::filesystem::exists(tmpFilePath))
|
||||
{
|
||||
auto deletedZoneSetsJson = json::from_file(tmpFilePath);
|
||||
try
|
||||
{
|
||||
auto deletedCustomZoneSets = deletedZoneSetsJson->GetNamedArray(NonLocalizable::DeletedCustomZoneSetsStr);
|
||||
for (auto zoneSet : deletedCustomZoneSets)
|
||||
{
|
||||
std::wstring uuid = L"{" + std::wstring{ zoneSet.GetString() } + L"}";
|
||||
result.push_back(uuid);
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
{
|
||||
}
|
||||
|
||||
DeleteTmpFile(tmpFilePath);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user