[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:
Seraphima Zykova
2021-01-27 21:33:52 +03:00
committed by GitHub
parent eb15cdde1b
commit 646d61bd4d
61 changed files with 3664 additions and 2781 deletions

View File

@@ -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;
}
}