mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-04 02:06:36 +02:00
[Workspaces] implement the move feature (#35480)
* [Workspaces] Add move functionality * spell checker * [Workspaces] Modify Arranger to move apps without launch * moved ipc helper * removed callback * use LauncherStatus in WindowArranger * wait for launching next app * launch in a separate thread and protect by mutexes * update app version in advance * changed canceling launch * increased waiting time * Fix optional parameter load from json * changed arranger waiting time * additional waiting time for Outlook * added app id * ensure ids before launch * set id in editor * minor updates * [Workspaces] Move: Get the nearest window when moving a window * [Workspaces] convert optional boolean to enum to avoid json problems * Handle case when the new Application Property "moveIfExists" does not exist * Re-implementing app-window pairing for moving feature. * spell checker * XAML formatting * Fixing bug: IPC message not arriving * spell checker * Removing app-level-setting for move app. Also fixed compiler errors due styling. * Updating editor window layout * Re-implementing window positioning UI elements * XAML formatting * Code review findings * Code cleanup * Code cleanup * Code cleanup * code cleanup * Code cleanup * Code cleanup * fix Move attribute after launch and snapshot * Extend WindowArranger with PWA functionality to detect different PWA apps. PwaHelper moved to the common library * fix repeat counter in the editor * Code optimization * code cleanup, optimization * fix double-processing window --------- Co-authored-by: Seraphima <zykovas91@gmail.com> Co-authored-by: donlaci <donlaci@yahoo.com>
This commit is contained in:
@@ -3,9 +3,6 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Workspaces.Data;
|
||||
|
||||
using static WorkspacesEditor.Data.ProjectData;
|
||||
|
||||
namespace WorkspacesEditor.Data
|
||||
|
||||
@@ -8,13 +8,7 @@ namespace WorkspacesEditor.Data
|
||||
{
|
||||
public class TempProjectData : ProjectData
|
||||
{
|
||||
public static string File
|
||||
{
|
||||
get
|
||||
{
|
||||
return FolderUtils.DataFolder() + "\\temp-workspaces.json";
|
||||
}
|
||||
}
|
||||
public static string File => FolderUtils.DataFolder() + "\\temp-workspaces.json";
|
||||
|
||||
public static void DeleteTempFile()
|
||||
{
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Workspaces.Data;
|
||||
using WorkspacesEditor.Utils;
|
||||
|
||||
using static WorkspacesEditor.Data.ProjectData;
|
||||
@@ -14,13 +12,7 @@ namespace WorkspacesEditor.Data
|
||||
{
|
||||
public class WorkspacesData : WorkspacesEditorData<WorkspacesListWrapper>
|
||||
{
|
||||
public string File
|
||||
{
|
||||
get
|
||||
{
|
||||
return FolderUtils.DataFolder() + "\\workspaces.json";
|
||||
}
|
||||
}
|
||||
public string File => FolderUtils.DataFolder() + "\\workspaces.json";
|
||||
|
||||
public struct WorkspacesListWrapper
|
||||
{
|
||||
|
||||
@@ -3,28 +3,24 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Text.Json;
|
||||
|
||||
using WorkspacesEditor.Utils;
|
||||
|
||||
namespace Workspaces.Data
|
||||
namespace WorkspacesEditor.Data
|
||||
{
|
||||
public class WorkspacesEditorData<T>
|
||||
{
|
||||
protected JsonSerializerOptions JsonOptions
|
||||
{
|
||||
get
|
||||
get => new()
|
||||
{
|
||||
return new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = new DashCaseNamingPolicy(),
|
||||
WriteIndented = true,
|
||||
};
|
||||
}
|
||||
PropertyNamingPolicy = new DashCaseNamingPolicy(),
|
||||
WriteIndented = true,
|
||||
};
|
||||
}
|
||||
|
||||
public T Read(string file)
|
||||
{
|
||||
IOUtils ioUtils = new IOUtils();
|
||||
IOUtils ioUtils = new();
|
||||
string data = ioUtils.ReadFile(file);
|
||||
return JsonSerializer.Deserialize<T>(data, JsonOptions);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
xmlns:ui="http://schemas.modernwpf.com/2019"
|
||||
x:Name="WorkspacesMainWindow"
|
||||
Title="{x:Static props:Resources.MainTitle}"
|
||||
MinWidth="700"
|
||||
MinWidth="750"
|
||||
MinHeight="680"
|
||||
ui:TitleBar.Background="{DynamicResource PrimaryBackgroundBrush}"
|
||||
ui:TitleBar.InactiveBackground="{DynamicResource TertiaryBackgroundBrush}"
|
||||
|
||||
@@ -18,14 +18,7 @@ namespace WorkspacesEditor.Models
|
||||
|
||||
public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
|
||||
{
|
||||
if (item is MonitorHeaderRow)
|
||||
{
|
||||
return HeaderTemplate;
|
||||
}
|
||||
else
|
||||
{
|
||||
return AppTemplate;
|
||||
}
|
||||
return item is MonitorHeaderRow ? HeaderTemplate : AppTemplate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,22 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// 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.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Media.Imaging;
|
||||
using ManagedCommon;
|
||||
using Windows.Management.Deployment;
|
||||
using WorkspacesCsharpLibrary;
|
||||
using WorkspacesCsharpLibrary.Models;
|
||||
|
||||
namespace WorkspacesEditor.Models
|
||||
{
|
||||
public enum WindowPositionKind
|
||||
{
|
||||
Custom = 0,
|
||||
Maximized = 1,
|
||||
Minimized = 2,
|
||||
}
|
||||
|
||||
public class Application : BaseApplication, IDisposable
|
||||
{
|
||||
private bool _isInitialized;
|
||||
@@ -79,7 +76,7 @@ namespace WorkspacesEditor.Models
|
||||
return left.X != right.X || left.Y != right.Y || left.Width != right.Width || left.Height != right.Height;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
public override readonly bool Equals(object obj)
|
||||
{
|
||||
if (obj == null || GetType() != obj.GetType())
|
||||
{
|
||||
@@ -90,7 +87,7 @@ namespace WorkspacesEditor.Models
|
||||
return X == pos.X && Y == pos.Y && Width == pos.Width && Height == pos.Height;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
public override readonly int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
@@ -136,36 +133,24 @@ namespace WorkspacesEditor.Models
|
||||
}
|
||||
}
|
||||
|
||||
private bool _minimized;
|
||||
public bool Minimized { get; set; }
|
||||
|
||||
public bool Minimized
|
||||
public bool Maximized { get; set; }
|
||||
|
||||
public bool EditPositionEnabled => !Minimized && !Maximized;
|
||||
|
||||
public int PositionComboboxIndex
|
||||
{
|
||||
get => _minimized;
|
||||
get => Maximized ? (int)WindowPositionKind.Maximized : Minimized ? (int)WindowPositionKind.Minimized : (int)WindowPositionKind.Custom;
|
||||
set
|
||||
{
|
||||
_minimized = value;
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(Minimized)));
|
||||
Maximized = value == (int)WindowPositionKind.Maximized;
|
||||
Minimized = value == (int)WindowPositionKind.Minimized;
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(EditPositionEnabled)));
|
||||
RedrawPreviewImage();
|
||||
}
|
||||
}
|
||||
|
||||
private bool _maximized;
|
||||
|
||||
public bool Maximized
|
||||
{
|
||||
get => _maximized;
|
||||
set
|
||||
{
|
||||
_maximized = value;
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(Maximized)));
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(EditPositionEnabled)));
|
||||
RedrawPreviewImage();
|
||||
}
|
||||
}
|
||||
|
||||
public bool EditPositionEnabled { get => !Minimized && !Maximized; }
|
||||
|
||||
private string _appMainParams;
|
||||
|
||||
public string AppMainParams
|
||||
@@ -183,7 +168,7 @@ namespace WorkspacesEditor.Models
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsAppMainParamVisible { get => !string.IsNullOrWhiteSpace(_appMainParams); }
|
||||
public bool IsAppMainParamVisible => !string.IsNullOrWhiteSpace(_appMainParams);
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsHighlighted { get; set; }
|
||||
@@ -192,13 +177,7 @@ namespace WorkspacesEditor.Models
|
||||
public int RepeatIndex { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public string RepeatIndexString
|
||||
{
|
||||
get
|
||||
{
|
||||
return RepeatIndex <= 1 ? string.Empty : RepeatIndex.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
public string RepeatIndexString => RepeatIndex <= 1 ? string.Empty : RepeatIndex.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
private WindowPosition _position;
|
||||
|
||||
@@ -242,10 +221,7 @@ namespace WorkspacesEditor.Models
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_monitorSetup == null)
|
||||
{
|
||||
_monitorSetup = Parent.GetMonitorForApp(this);
|
||||
}
|
||||
_monitorSetup ??= Parent.GetMonitorForApp(this);
|
||||
|
||||
return _monitorSetup;
|
||||
}
|
||||
@@ -271,7 +247,7 @@ namespace WorkspacesEditor.Models
|
||||
}
|
||||
}
|
||||
|
||||
public string DeleteButtonContent { get => _isIncluded ? Properties.Resources.Delete : Properties.Resources.AddBack; }
|
||||
public string DeleteButtonContent => _isIncluded ? Properties.Resources.Delete : Properties.Resources.AddBack;
|
||||
|
||||
private bool _isIncluded = true;
|
||||
|
||||
@@ -298,15 +274,5 @@ namespace WorkspacesEditor.Models
|
||||
CommandLineArguments = newCommandLineValue;
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(AppMainParams)));
|
||||
}
|
||||
|
||||
internal void MaximizedChecked()
|
||||
{
|
||||
Minimized = false;
|
||||
}
|
||||
|
||||
internal void MinimizedChecked()
|
||||
{
|
||||
Maximized = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,28 +6,18 @@ using System.Windows;
|
||||
|
||||
namespace WorkspacesEditor.Models
|
||||
{
|
||||
public class Monitor
|
||||
public class Monitor(string monitorName, string monitorInstanceId, int number, int dpi, Rect dpiAwareBounds, Rect dpiUnawareBounds)
|
||||
{
|
||||
public string MonitorName { get; private set; }
|
||||
public string MonitorName { get; private set; } = monitorName;
|
||||
|
||||
public string MonitorInstanceId { get; private set; }
|
||||
public string MonitorInstanceId { get; private set; } = monitorInstanceId;
|
||||
|
||||
public int MonitorNumber { get; private set; }
|
||||
public int MonitorNumber { get; private set; } = number;
|
||||
|
||||
public int Dpi { get; private set; }
|
||||
public int Dpi { get; private set; } = dpi;
|
||||
|
||||
public Rect MonitorDpiUnawareBounds { get; private set; }
|
||||
public Rect MonitorDpiUnawareBounds { get; private set; } = dpiUnawareBounds;
|
||||
|
||||
public Rect MonitorDpiAwareBounds { get; private set; }
|
||||
|
||||
public Monitor(string monitorName, string monitorInstanceId, int number, int dpi, Rect dpiAwareBounds, Rect dpiUnawareBounds)
|
||||
{
|
||||
MonitorName = monitorName;
|
||||
MonitorInstanceId = monitorInstanceId;
|
||||
MonitorNumber = number;
|
||||
Dpi = dpi;
|
||||
MonitorDpiAwareBounds = dpiAwareBounds;
|
||||
MonitorDpiUnawareBounds = dpiUnawareBounds;
|
||||
}
|
||||
public Rect MonitorDpiAwareBounds { get; private set; } = dpiAwareBounds;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@ namespace WorkspacesEditor.Models
|
||||
PropertyChanged?.Invoke(this, e);
|
||||
}
|
||||
|
||||
public string MonitorInfo { get => MonitorName; }
|
||||
public string MonitorInfo => MonitorName;
|
||||
|
||||
public string MonitorInfoWithResolution { get => $"{MonitorName} {MonitorDpiAwareBounds.Width}x{MonitorDpiAwareBounds.Height}"; }
|
||||
public string MonitorInfoWithResolution => $"{MonitorName} {MonitorDpiAwareBounds.Width}x{MonitorDpiAwareBounds.Height}";
|
||||
|
||||
public MonitorSetup(string monitorName, string monitorInstanceId, int number, int dpi, Rect dpiAwareBounds, Rect dpiUnawareBounds)
|
||||
: base(monitorName, monitorInstanceId, number, dpi, dpiAwareBounds, dpiUnawareBounds)
|
||||
|
||||
@@ -29,10 +29,7 @@ namespace WorkspacesEditor.Models
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
get => _name;
|
||||
|
||||
set
|
||||
{
|
||||
@@ -68,8 +65,7 @@ namespace WorkspacesEditor.Models
|
||||
|
||||
DateTime lastLaunchDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(LastLaunchedTime);
|
||||
|
||||
var now = DateTime.UtcNow.Ticks;
|
||||
var ts = DateTime.UtcNow - lastLaunchDateTime;
|
||||
TimeSpan ts = DateTime.UtcNow - lastLaunchDateTime;
|
||||
double delta = Math.Abs(ts.TotalSeconds);
|
||||
|
||||
if (delta < 1 * MINUTE)
|
||||
@@ -120,10 +116,7 @@ namespace WorkspacesEditor.Models
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanBeSaved
|
||||
{
|
||||
get => Name.Length > 0 && Applications.Count > 0;
|
||||
}
|
||||
public bool CanBeSaved => Name.Length > 0 && Applications.Count > 0;
|
||||
|
||||
private bool _isRevertEnabled;
|
||||
|
||||
@@ -145,10 +138,7 @@ namespace WorkspacesEditor.Models
|
||||
[JsonIgnore]
|
||||
public bool IsPopupVisible
|
||||
{
|
||||
get
|
||||
{
|
||||
return _isPopupVisible;
|
||||
}
|
||||
get => _isPopupVisible;
|
||||
|
||||
set
|
||||
{
|
||||
@@ -163,11 +153,11 @@ namespace WorkspacesEditor.Models
|
||||
{
|
||||
get
|
||||
{
|
||||
List<object> applicationsListed = new List<object>();
|
||||
List<object> applicationsListed = [];
|
||||
ILookup<MonitorSetup, Application> apps = Applications.Where(x => !x.Minimized).ToLookup(x => x.MonitorSetup);
|
||||
foreach (var appItem in apps.OrderBy(x => x.Key.MonitorDpiUnawareBounds.Left).ThenBy(x => x.Key.MonitorDpiUnawareBounds.Top))
|
||||
foreach (IGrouping<MonitorSetup, Application> appItem in apps.OrderBy(x => x.Key.MonitorDpiUnawareBounds.Left).ThenBy(x => x.Key.MonitorDpiUnawareBounds.Top))
|
||||
{
|
||||
MonitorHeaderRow headerRow = new MonitorHeaderRow { MonitorName = "Screen " + appItem.Key.MonitorNumber, SelectString = Properties.Resources.SelectAllAppsOnMonitor + " " + appItem.Key.MonitorInfo };
|
||||
MonitorHeaderRow headerRow = new() { MonitorName = "Screen " + appItem.Key.MonitorNumber, SelectString = Properties.Resources.SelectAllAppsOnMonitor + " " + appItem.Key.MonitorInfo };
|
||||
applicationsListed.Add(headerRow);
|
||||
foreach (Application app in appItem)
|
||||
{
|
||||
@@ -175,10 +165,10 @@ namespace WorkspacesEditor.Models
|
||||
}
|
||||
}
|
||||
|
||||
var minimizedApps = Applications.Where(x => x.Minimized);
|
||||
IEnumerable<Application> minimizedApps = Applications.Where(x => x.Minimized);
|
||||
if (minimizedApps.Any())
|
||||
{
|
||||
MonitorHeaderRow headerRow = new MonitorHeaderRow { MonitorName = Properties.Resources.Minimized_Apps, SelectString = Properties.Resources.SelectAllMinimizedApps };
|
||||
MonitorHeaderRow headerRow = new() { MonitorName = Properties.Resources.Minimized_Apps, SelectString = Properties.Resources.SelectAllMinimizedApps };
|
||||
applicationsListed.Add(headerRow);
|
||||
foreach (Application app in minimizedApps)
|
||||
{
|
||||
@@ -219,17 +209,17 @@ namespace WorkspacesEditor.Models
|
||||
|
||||
int screenIndex = 1;
|
||||
|
||||
Monitors = new List<MonitorSetup>();
|
||||
foreach (var item in selectedProject.Monitors.OrderBy(x => x.MonitorDpiAwareBounds.Left).ThenBy(x => x.MonitorDpiAwareBounds.Top))
|
||||
Monitors = [];
|
||||
foreach (MonitorSetup item in selectedProject.Monitors.OrderBy(x => x.MonitorDpiAwareBounds.Left).ThenBy(x => x.MonitorDpiAwareBounds.Top))
|
||||
{
|
||||
Monitors.Add(item);
|
||||
screenIndex++;
|
||||
}
|
||||
|
||||
Applications = new List<Application>();
|
||||
foreach (var item in selectedProject.Applications)
|
||||
Applications = [];
|
||||
foreach (Application item in selectedProject.Applications)
|
||||
{
|
||||
Application newApp = new Application(item);
|
||||
Application newApp = new(item);
|
||||
newApp.Parent = this;
|
||||
newApp.InitializationFinished();
|
||||
Applications.Add(newApp);
|
||||
@@ -244,14 +234,14 @@ namespace WorkspacesEditor.Models
|
||||
LastLaunchedTime = project.LastLaunchedTime;
|
||||
IsShortcutNeeded = project.IsShortcutNeeded;
|
||||
MoveExistingWindows = project.MoveExistingWindows;
|
||||
Monitors = new List<MonitorSetup>() { };
|
||||
Applications = new List<Models.Application> { };
|
||||
Monitors = [];
|
||||
Applications = [];
|
||||
|
||||
foreach (var app in project.Applications)
|
||||
foreach (ProjectData.ApplicationWrapper app in project.Applications)
|
||||
{
|
||||
Models.Application newApp = new Models.Application()
|
||||
Models.Application newApp = new()
|
||||
{
|
||||
Id = string.IsNullOrEmpty(app.Id) ? $"{{{Guid.NewGuid().ToString()}}}" : app.Id,
|
||||
Id = string.IsNullOrEmpty(app.Id) ? $"{{{Guid.NewGuid()}}}" : app.Id,
|
||||
AppName = app.Application,
|
||||
AppPath = app.ApplicationPath,
|
||||
AppTitle = app.Title,
|
||||
@@ -278,20 +268,17 @@ namespace WorkspacesEditor.Models
|
||||
Applications.Add(newApp);
|
||||
}
|
||||
|
||||
foreach (var monitor in project.MonitorConfiguration)
|
||||
foreach (ProjectData.MonitorConfigurationWrapper monitor in project.MonitorConfiguration)
|
||||
{
|
||||
System.Windows.Rect dpiAware = new System.Windows.Rect(monitor.MonitorRectDpiAware.Left, monitor.MonitorRectDpiAware.Top, monitor.MonitorRectDpiAware.Width, monitor.MonitorRectDpiAware.Height);
|
||||
System.Windows.Rect dpiUnaware = new System.Windows.Rect(monitor.MonitorRectDpiUnaware.Left, monitor.MonitorRectDpiUnaware.Top, monitor.MonitorRectDpiUnaware.Width, monitor.MonitorRectDpiUnaware.Height);
|
||||
System.Windows.Rect dpiAware = new(monitor.MonitorRectDpiAware.Left, monitor.MonitorRectDpiAware.Top, monitor.MonitorRectDpiAware.Width, monitor.MonitorRectDpiAware.Height);
|
||||
System.Windows.Rect dpiUnaware = new(monitor.MonitorRectDpiUnaware.Left, monitor.MonitorRectDpiUnaware.Top, monitor.MonitorRectDpiUnaware.Width, monitor.MonitorRectDpiUnaware.Height);
|
||||
Monitors.Add(new MonitorSetup(monitor.Id, monitor.InstanceId, monitor.MonitorNumber, monitor.Dpi, dpiAware, dpiUnaware));
|
||||
}
|
||||
}
|
||||
|
||||
public BitmapImage PreviewIcons
|
||||
{
|
||||
get
|
||||
{
|
||||
return _previewIcons;
|
||||
}
|
||||
get => _previewIcons;
|
||||
|
||||
set
|
||||
{
|
||||
@@ -302,10 +289,7 @@ namespace WorkspacesEditor.Models
|
||||
|
||||
public BitmapImage PreviewImage
|
||||
{
|
||||
get
|
||||
{
|
||||
return _previewImage;
|
||||
}
|
||||
get => _previewImage;
|
||||
|
||||
set
|
||||
{
|
||||
@@ -316,10 +300,7 @@ namespace WorkspacesEditor.Models
|
||||
|
||||
public double PreviewImageWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return _previewImageWidth;
|
||||
}
|
||||
get => _previewImageWidth;
|
||||
|
||||
set
|
||||
{
|
||||
@@ -366,6 +347,7 @@ namespace WorkspacesEditor.Models
|
||||
Id = other.Id;
|
||||
Name = other.Name;
|
||||
IsRevertEnabled = true;
|
||||
MoveExistingWindows = other.MoveExistingWindows;
|
||||
}
|
||||
|
||||
internal void CloseExpanders()
|
||||
@@ -378,13 +360,13 @@ namespace WorkspacesEditor.Models
|
||||
|
||||
internal MonitorSetup GetMonitorForApp(Application app)
|
||||
{
|
||||
var monitorSetup = Monitors.Where(x => x.MonitorNumber == app.MonitorNumber).FirstOrDefault();
|
||||
MonitorSetup monitorSetup = Monitors.Where(x => x.MonitorNumber == app.MonitorNumber).FirstOrDefault();
|
||||
if (monitorSetup == null)
|
||||
{
|
||||
// monitors changed: try to determine monitor id based on middle point
|
||||
int middleX = app.Position.X + (app.Position.Width / 2);
|
||||
int middleY = app.Position.Y + (app.Position.Height / 2);
|
||||
var monitorCandidate = Monitors.Where(x =>
|
||||
MonitorSetup monitorCandidate = Monitors.Where(x =>
|
||||
(x.MonitorDpiUnawareBounds.Left < middleX) &&
|
||||
(x.MonitorDpiUnawareBounds.Right > middleX) &&
|
||||
(x.MonitorDpiUnawareBounds.Top < middleY) &&
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Add Back.
|
||||
/// Looks up a localized string similar to Add back.
|
||||
/// </summary>
|
||||
public static string AddBack {
|
||||
get {
|
||||
@@ -78,15 +78,6 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Launch new app instances.
|
||||
/// </summary>
|
||||
public static string AlwaysLaunch {
|
||||
get {
|
||||
return ResourceManager.GetString("AlwaysLaunch", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to app.
|
||||
/// </summary>
|
||||
@@ -169,7 +160,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Create Desktop Shortcut.
|
||||
/// Looks up a localized string similar to Create desktop shortcut.
|
||||
/// </summary>
|
||||
public static string CreateShortcut {
|
||||
get {
|
||||
@@ -186,6 +177,15 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Custom.
|
||||
/// </summary>
|
||||
public static string Custom {
|
||||
get {
|
||||
return ResourceManager.GetString("Custom", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to days ago.
|
||||
/// </summary>
|
||||
@@ -223,7 +223,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Remove Selected Apps.
|
||||
/// Looks up a localized string similar to Remove selected apps.
|
||||
/// </summary>
|
||||
public static string DeleteSelected {
|
||||
get {
|
||||
@@ -322,7 +322,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Launch & Edit.
|
||||
/// Looks up a localized string similar to Launch & edit.
|
||||
/// </summary>
|
||||
public static string LaunchEdit {
|
||||
get {
|
||||
@@ -367,7 +367,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Minimized Apps.
|
||||
/// Looks up a localized string similar to Minimized apps.
|
||||
/// </summary>
|
||||
public static string Minimized_Apps {
|
||||
get {
|
||||
@@ -394,7 +394,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Move apps if present.
|
||||
/// Looks up a localized string similar to Move existing windows.
|
||||
/// </summary>
|
||||
public static string MoveIfExist {
|
||||
get {
|
||||
@@ -502,7 +502,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Pin Workspaces to Taskbar.
|
||||
/// Looks up a localized string similar to Pin Workspaces to taskbar.
|
||||
/// </summary>
|
||||
public static string PinToTaskbar {
|
||||
get {
|
||||
@@ -565,7 +565,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Select All Apps on.
|
||||
/// Looks up a localized string similar to Select all apps on.
|
||||
/// </summary>
|
||||
public static string SelectAllAppsOnMonitor {
|
||||
get {
|
||||
@@ -574,7 +574,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Select All Minimized Apps.
|
||||
/// Looks up a localized string similar to Select all minimized apps.
|
||||
/// </summary>
|
||||
public static string SelectAllMinimizedApps {
|
||||
get {
|
||||
@@ -583,7 +583,7 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Select All Apps in Workspace.
|
||||
/// Looks up a localized string similar to Select all apps in Workspace.
|
||||
/// </summary>
|
||||
public static string SelectedAllInWorkspace {
|
||||
get {
|
||||
@@ -645,6 +645,15 @@ namespace WorkspacesEditor.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Window position.
|
||||
/// </summary>
|
||||
public static string WindowPosition {
|
||||
get {
|
||||
return ResourceManager.GetString("WindowPosition", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Workspace name.
|
||||
/// </summary>
|
||||
|
||||
@@ -123,9 +123,6 @@
|
||||
<data name="Admin" xml:space="preserve">
|
||||
<value>Admin</value>
|
||||
</data>
|
||||
<data name="AlwaysLaunch" xml:space="preserve">
|
||||
<value>Launch new app instances</value>
|
||||
</data>
|
||||
<data name="App" xml:space="preserve">
|
||||
<value>app</value>
|
||||
</data>
|
||||
@@ -160,6 +157,9 @@
|
||||
<data name="CreateShortcut" xml:space="preserve">
|
||||
<value>Create desktop shortcut</value>
|
||||
</data>
|
||||
<data name="Custom" xml:space="preserve">
|
||||
<value>Custom</value>
|
||||
</data>
|
||||
<data name="DaysAgo" xml:space="preserve">
|
||||
<value>days ago</value>
|
||||
</data>
|
||||
@@ -231,7 +231,7 @@
|
||||
<value>months ago</value>
|
||||
</data>
|
||||
<data name="MoveIfExist" xml:space="preserve">
|
||||
<value>Move apps if present</value>
|
||||
<value>Move existing windows</value>
|
||||
</data>
|
||||
<data name="Name" xml:space="preserve">
|
||||
<value>Name</value>
|
||||
@@ -321,6 +321,9 @@
|
||||
<data name="Width" xml:space="preserve">
|
||||
<value>Width</value>
|
||||
</data>
|
||||
<data name="WindowPosition" xml:space="preserve">
|
||||
<value>Window position</value>
|
||||
</data>
|
||||
<data name="WriteArgs" xml:space="preserve">
|
||||
<value>Write arguments here</value>
|
||||
</data>
|
||||
|
||||
@@ -20,21 +20,21 @@ namespace WorkspacesEditor.Utils
|
||||
{
|
||||
public class DrawHelper
|
||||
{
|
||||
private static Font font = new("Tahoma", 24);
|
||||
private static double scale = 0.1;
|
||||
private static readonly Font Font = new("Tahoma", 24);
|
||||
private static readonly double Scale = 0.1;
|
||||
private static double gapWidth;
|
||||
private static double gapHeight;
|
||||
|
||||
public static BitmapImage DrawPreview(Project project, Rectangle bounds, Theme currentTheme)
|
||||
{
|
||||
List<double> horizontalGaps = new List<double>();
|
||||
List<double> verticalGaps = new List<double>();
|
||||
List<double> horizontalGaps = [];
|
||||
List<double> verticalGaps = [];
|
||||
gapWidth = bounds.Width * 0.01;
|
||||
gapHeight = bounds.Height * 0.01;
|
||||
|
||||
int Scaled(double value)
|
||||
{
|
||||
return (int)(value * scale);
|
||||
return (int)(value * Scale);
|
||||
}
|
||||
|
||||
int TransformX(double posX)
|
||||
@@ -54,7 +54,7 @@ namespace WorkspacesEditor.Utils
|
||||
if (app.Maximized)
|
||||
{
|
||||
Project project = app.Parent;
|
||||
var monitor = project.GetMonitorForApp(app);
|
||||
MonitorSetup monitor = project.GetMonitorForApp(app);
|
||||
if (monitor == null)
|
||||
{
|
||||
// unrealistic case, there are no monitors at all in the workspace, use original rect
|
||||
@@ -69,22 +69,23 @@ namespace WorkspacesEditor.Utils
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary<string, int> repeatCounter = new Dictionary<string, int>();
|
||||
Dictionary<string, int> repeatCounter = [];
|
||||
|
||||
var appsIncluded = project.Applications.Where(x => x.IsIncluded);
|
||||
IEnumerable<Application> appsIncluded = project.Applications.Where(x => x.IsIncluded);
|
||||
|
||||
foreach (Application app in appsIncluded)
|
||||
{
|
||||
if (repeatCounter.TryGetValue(app.AppPath + app.AppTitle, out int value))
|
||||
string appIdentifier = app.AppPath + app.PwaAppId;
|
||||
if (repeatCounter.TryGetValue(appIdentifier, out int value))
|
||||
{
|
||||
repeatCounter[app.AppPath + app.AppTitle] = ++value;
|
||||
repeatCounter[appIdentifier] = ++value;
|
||||
}
|
||||
else
|
||||
{
|
||||
repeatCounter.Add(app.AppPath + app.AppTitle, 1);
|
||||
repeatCounter.Add(appIdentifier, 1);
|
||||
}
|
||||
|
||||
app.RepeatIndex = repeatCounter[app.AppPath + app.AppTitle];
|
||||
app.RepeatIndex = repeatCounter[appIdentifier];
|
||||
}
|
||||
|
||||
foreach (Application app in project.Applications.Where(x => !x.IsIncluded))
|
||||
@@ -113,7 +114,7 @@ namespace WorkspacesEditor.Utils
|
||||
}
|
||||
}
|
||||
|
||||
Bitmap previewBitmap = new Bitmap(Scaled(bounds.Width + (verticalGaps.Count * gapWidth)), Scaled((bounds.Height * 1.2) + (horizontalGaps.Count * gapHeight)));
|
||||
Bitmap previewBitmap = new(Scaled(bounds.Width + (verticalGaps.Count * gapWidth)), Scaled((bounds.Height * 1.2) + (horizontalGaps.Count * gapHeight)));
|
||||
double desiredIconSize = Scaled(Math.Min(bounds.Width, bounds.Height)) * 0.25;
|
||||
using (Graphics g = Graphics.FromImage(previewBitmap))
|
||||
{
|
||||
@@ -131,7 +132,7 @@ namespace WorkspacesEditor.Utils
|
||||
g.FillRectangle(monitorBrush, new Rectangle(TransformX(monitor.MonitorDpiAwareBounds.Left), TransformY(monitor.MonitorDpiAwareBounds.Top), Scaled(monitor.MonitorDpiAwareBounds.Width), Scaled(monitor.MonitorDpiAwareBounds.Height)));
|
||||
}
|
||||
|
||||
var appsToDraw = appsIncluded.Where(x => !x.Minimized);
|
||||
IEnumerable<Application> appsToDraw = appsIncluded.Where(x => !x.Minimized);
|
||||
|
||||
// draw the highlighted app at the end to have its icon in the foreground for the case there are overlapping icons
|
||||
foreach (Application app in appsToDraw.Where(x => !x.IsHighlighted))
|
||||
@@ -147,24 +148,22 @@ namespace WorkspacesEditor.Utils
|
||||
}
|
||||
|
||||
// draw the minimized windows
|
||||
Rectangle rectMinimized = new Rectangle(0, Scaled((bounds.Height * 1.02) + (horizontalGaps.Count * gapHeight)), Scaled(bounds.Width + (verticalGaps.Count * gapWidth)), Scaled(bounds.Height * 0.18));
|
||||
Rectangle rectMinimized = new(0, Scaled((bounds.Height * 1.02) + (horizontalGaps.Count * gapHeight)), Scaled(bounds.Width + (verticalGaps.Count * gapWidth)), Scaled(bounds.Height * 0.18));
|
||||
DrawWindow(g, brush, brushForHighlight, rectMinimized, appsIncluded.Where(x => x.Minimized), currentTheme);
|
||||
}
|
||||
|
||||
using (var memory = new MemoryStream())
|
||||
{
|
||||
previewBitmap.Save(memory, ImageFormat.Png);
|
||||
memory.Position = 0;
|
||||
using MemoryStream memory = new();
|
||||
previewBitmap.Save(memory, ImageFormat.Png);
|
||||
memory.Position = 0;
|
||||
|
||||
var bitmapImage = new BitmapImage();
|
||||
bitmapImage.BeginInit();
|
||||
bitmapImage.StreamSource = memory;
|
||||
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
|
||||
bitmapImage.EndInit();
|
||||
bitmapImage.Freeze();
|
||||
BitmapImage bitmapImage = new();
|
||||
bitmapImage.BeginInit();
|
||||
bitmapImage.StreamSource = memory;
|
||||
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
|
||||
bitmapImage.EndInit();
|
||||
bitmapImage.Freeze();
|
||||
|
||||
return bitmapImage;
|
||||
}
|
||||
return bitmapImage;
|
||||
}
|
||||
|
||||
public static void DrawWindow(Graphics graphics, Brush brush, Rectangle bounds, Application app, double desiredIconSize, Theme currentTheme)
|
||||
@@ -194,7 +193,7 @@ namespace WorkspacesEditor.Utils
|
||||
}
|
||||
|
||||
double iconSize = Math.Min(Math.Min(bounds.Width - 4, bounds.Height - 4), desiredIconSize);
|
||||
Rectangle iconBounds = new Rectangle((int)(bounds.Left + (bounds.Width / 2) - (iconSize / 2)), (int)(bounds.Top + (bounds.Height / 2) - (iconSize / 2)), (int)iconSize, (int)iconSize);
|
||||
Rectangle iconBounds = new((int)(bounds.Left + (bounds.Width / 2) - (iconSize / 2)), (int)(bounds.Top + (bounds.Height / 2) - (iconSize / 2)), (int)iconSize, (int)iconSize);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -203,13 +202,13 @@ namespace WorkspacesEditor.Utils
|
||||
{
|
||||
string indexString = app.RepeatIndex.ToString(CultureInfo.InvariantCulture);
|
||||
int indexSize = (int)(iconBounds.Width * 0.5);
|
||||
Rectangle indexBounds = new Rectangle(iconBounds.Right - indexSize, iconBounds.Bottom - indexSize, indexSize, indexSize);
|
||||
Rectangle indexBounds = new(iconBounds.Right - indexSize, iconBounds.Bottom - indexSize, indexSize, indexSize);
|
||||
|
||||
var textSize = graphics.MeasureString(indexString, font);
|
||||
var state = graphics.Save();
|
||||
SizeF textSize = graphics.MeasureString(indexString, Font);
|
||||
GraphicsState state = graphics.Save();
|
||||
graphics.TranslateTransform(indexBounds.Left, indexBounds.Top);
|
||||
graphics.ScaleTransform(indexBounds.Width / textSize.Width, indexBounds.Height / textSize.Height);
|
||||
graphics.DrawString(indexString, font, Brushes.Black, PointF.Empty);
|
||||
graphics.DrawString(indexString, Font, Brushes.Black, PointF.Empty);
|
||||
graphics.Restore(state);
|
||||
}
|
||||
}
|
||||
@@ -255,7 +254,7 @@ namespace WorkspacesEditor.Utils
|
||||
for (int iconCounter = 0; iconCounter < appsCount; iconCounter++)
|
||||
{
|
||||
Application app = apps.ElementAt(iconCounter);
|
||||
Rectangle iconBounds = new Rectangle((int)(bounds.Left + (bounds.Width / 2) - (iconSize * ((appsCount / 2) - iconCounter))), (int)(bounds.Top + (bounds.Height / 2) - (iconSize / 2)), (int)iconSize, (int)iconSize);
|
||||
Rectangle iconBounds = new((int)(bounds.Left + (bounds.Width / 2) - (iconSize * ((appsCount / 2) - iconCounter))), (int)(bounds.Top + (bounds.Height / 2) - (iconSize / 2)), (int)iconSize, (int)iconSize);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -264,13 +263,13 @@ namespace WorkspacesEditor.Utils
|
||||
{
|
||||
string indexString = app.RepeatIndex.ToString(CultureInfo.InvariantCulture);
|
||||
int indexSize = (int)(iconBounds.Width * 0.5);
|
||||
Rectangle indexBounds = new Rectangle(iconBounds.Right - indexSize, iconBounds.Bottom - indexSize, indexSize, indexSize);
|
||||
Rectangle indexBounds = new(iconBounds.Right - indexSize, iconBounds.Bottom - indexSize, indexSize, indexSize);
|
||||
|
||||
var textSize = graphics.MeasureString(indexString, font);
|
||||
var state = graphics.Save();
|
||||
SizeF textSize = graphics.MeasureString(indexString, Font);
|
||||
GraphicsState state = graphics.Save();
|
||||
graphics.TranslateTransform(indexBounds.Left, indexBounds.Top);
|
||||
graphics.ScaleTransform(indexBounds.Width / textSize.Width, indexBounds.Height / textSize.Height);
|
||||
graphics.DrawString(indexString, font, Brushes.Black, PointF.Empty);
|
||||
graphics.DrawString(indexString, Font, Brushes.Black, PointF.Empty);
|
||||
graphics.Restore(state);
|
||||
}
|
||||
}
|
||||
@@ -289,14 +288,14 @@ namespace WorkspacesEditor.Utils
|
||||
return null;
|
||||
}
|
||||
|
||||
Bitmap previewBitmap = new Bitmap(32 * appsCount, 24);
|
||||
Bitmap previewBitmap = new(32 * appsCount, 24);
|
||||
using (Graphics graphics = Graphics.FromImage(previewBitmap))
|
||||
{
|
||||
graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
int appIndex = 0;
|
||||
foreach (var app in project.Applications)
|
||||
foreach (Application app in project.Applications)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -311,20 +310,18 @@ namespace WorkspacesEditor.Utils
|
||||
}
|
||||
}
|
||||
|
||||
using (var memory = new MemoryStream())
|
||||
{
|
||||
previewBitmap.Save(memory, ImageFormat.Png);
|
||||
memory.Position = 0;
|
||||
using MemoryStream memory = new();
|
||||
previewBitmap.Save(memory, ImageFormat.Png);
|
||||
memory.Position = 0;
|
||||
|
||||
var bitmapImage = new BitmapImage();
|
||||
bitmapImage.BeginInit();
|
||||
bitmapImage.StreamSource = memory;
|
||||
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
|
||||
bitmapImage.EndInit();
|
||||
bitmapImage.Freeze();
|
||||
BitmapImage bitmapImage = new();
|
||||
bitmapImage.BeginInit();
|
||||
bitmapImage.StreamSource = memory;
|
||||
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
|
||||
bitmapImage.EndInit();
|
||||
bitmapImage.Freeze();
|
||||
|
||||
return bitmapImage;
|
||||
}
|
||||
return bitmapImage;
|
||||
}
|
||||
|
||||
private static GraphicsPath RoundedRect(Rectangle bounds)
|
||||
@@ -333,9 +330,9 @@ namespace WorkspacesEditor.Utils
|
||||
int radius = (int)(minorSize / 8);
|
||||
|
||||
int diameter = radius * 2;
|
||||
Size size = new Size(diameter, diameter);
|
||||
Rectangle arc = new Rectangle(bounds.Location, size);
|
||||
GraphicsPath path = new GraphicsPath();
|
||||
Size size = new(diameter, diameter);
|
||||
Rectangle arc = new(bounds.Location, size);
|
||||
GraphicsPath path = new();
|
||||
|
||||
if (radius == 0)
|
||||
{
|
||||
|
||||
@@ -26,18 +26,16 @@ namespace WorkspacesEditor.Utils
|
||||
{
|
||||
if (_fileSystem.File.Exists(fileName))
|
||||
{
|
||||
var attempts = 0;
|
||||
int attempts = 0;
|
||||
while (attempts < 10)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (FileSystemStream inputStream = _fileSystem.File.Open(fileName, FileMode.Open))
|
||||
using (StreamReader reader = new StreamReader(inputStream))
|
||||
{
|
||||
string data = reader.ReadToEnd();
|
||||
inputStream.Close();
|
||||
return data;
|
||||
}
|
||||
using FileSystemStream inputStream = _fileSystem.File.Open(fileName, FileMode.Open);
|
||||
using StreamReader reader = new(inputStream);
|
||||
string data = reader.ReadToEnd();
|
||||
inputStream.Close();
|
||||
return data;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace WorkspacesEditor.Utils
|
||||
|
||||
private Screen[] GetDpiUnawareScreenBounds()
|
||||
{
|
||||
Thread dpiUnawareThread = new Thread(new ThreadStart(SaveDpiUnawareScreens));
|
||||
Thread dpiUnawareThread = new(new ThreadStart(SaveDpiUnawareScreens));
|
||||
dpiUnawareThread.Start();
|
||||
dpiUnawareThread.Join();
|
||||
|
||||
@@ -35,15 +35,15 @@ namespace WorkspacesEditor.Utils
|
||||
|
||||
public static Screen[] GetDpiUnawareScreens()
|
||||
{
|
||||
MonitorHelper monitorHelper = new MonitorHelper();
|
||||
MonitorHelper monitorHelper = new();
|
||||
return monitorHelper.GetDpiUnawareScreenBounds();
|
||||
}
|
||||
|
||||
internal static double GetScreenDpiFromScreen(Screen screen)
|
||||
{
|
||||
var point = new System.Drawing.Point(screen.Bounds.Left + 1, screen.Bounds.Top + 1);
|
||||
var monitor = NativeMethods.MonitorFromPoint(point, NativeMethods._MONITOR_DEFAULTTONEAREST);
|
||||
NativeMethods.GetDpiForMonitor(monitor, NativeMethods.DpiType.EFFECTIVE, out uint dpiX, out uint dpiY);
|
||||
System.Drawing.Point point = new(screen.Bounds.Left + 1, screen.Bounds.Top + 1);
|
||||
nint monitor = NativeMethods.MonitorFromPoint(point, NativeMethods._MONITOR_DEFAULTTONEAREST);
|
||||
_ = NativeMethods.GetDpiForMonitor(monitor, NativeMethods.DpiType.EFFECTIVE, out uint dpiX, out _);
|
||||
return dpiX / 96.0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,19 +4,12 @@
|
||||
|
||||
namespace WorkspacesEditor.Utils
|
||||
{
|
||||
public struct ParsingResult
|
||||
public readonly struct ParsingResult(bool result, string message = "", string data = "")
|
||||
{
|
||||
public bool Result { get; }
|
||||
public bool Result { get; } = result;
|
||||
|
||||
public string Message { get; }
|
||||
public string Message { get; } = message;
|
||||
|
||||
public string MalformedData { get; }
|
||||
|
||||
public ParsingResult(bool result, string message = "", string data = "")
|
||||
{
|
||||
Result = result;
|
||||
Message = message;
|
||||
MalformedData = data;
|
||||
}
|
||||
public string MalformedData { get; } = data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,13 +9,13 @@ namespace WorkspacesEditor.Utils
|
||||
public class Settings
|
||||
{
|
||||
private const string WorkspacesModuleName = "Workspaces";
|
||||
private static SettingsUtils _settingsUtils = new SettingsUtils();
|
||||
private static readonly SettingsUtils _settingsUtils = new();
|
||||
|
||||
public static WorkspacesSettings ReadSettings()
|
||||
{
|
||||
if (!_settingsUtils.SettingsExists(WorkspacesModuleName))
|
||||
{
|
||||
var defaultWorkspacesSettings = new WorkspacesSettings();
|
||||
WorkspacesSettings defaultWorkspacesSettings = new();
|
||||
defaultWorkspacesSettings.Save(_settingsUtils);
|
||||
return defaultWorkspacesSettings;
|
||||
}
|
||||
|
||||
@@ -11,12 +11,9 @@ namespace WorkspacesEditor.Utils
|
||||
public static string UpperCamelCaseToDashCase(this string str)
|
||||
{
|
||||
// If it's single letter variable, leave it as it is
|
||||
if (str.Length == 1)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
return string.Concat(str.Select((x, i) => i > 0 && char.IsUpper(x) ? "-" + x.ToString() : x.ToString())).ToLowerInvariant();
|
||||
return str.Length == 1
|
||||
? str
|
||||
: string.Concat(str.Select((x, i) => i > 0 && char.IsUpper(x) ? "-" + x.ToString() : x.ToString())).ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace WorkspacesEditor.Utils
|
||||
{
|
||||
try
|
||||
{
|
||||
WorkspacesData parser = new WorkspacesData();
|
||||
WorkspacesData parser = new();
|
||||
if (!File.Exists(parser.File))
|
||||
{
|
||||
Logger.LogWarning($"Workspaces storage file not found: {parser.File}");
|
||||
@@ -56,14 +56,14 @@ namespace WorkspacesEditor.Utils
|
||||
{
|
||||
try
|
||||
{
|
||||
ProjectData parser = new ProjectData();
|
||||
ProjectData parser = new();
|
||||
if (!File.Exists(TempProjectData.File))
|
||||
{
|
||||
Logger.LogWarning($"ParseProject method. Workspaces storage file not found: {TempProjectData.File}");
|
||||
return null;
|
||||
}
|
||||
|
||||
Project project = new Project(parser.Read(TempProjectData.File));
|
||||
Project project = new(parser.Read(TempProjectData.File));
|
||||
return project;
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -75,13 +75,13 @@ namespace WorkspacesEditor.Utils
|
||||
|
||||
public void SerializeWorkspaces(List<Project> workspaces, bool useTempFile = false)
|
||||
{
|
||||
WorkspacesData serializer = new WorkspacesData();
|
||||
WorkspacesData.WorkspacesListWrapper workspacesWrapper = new WorkspacesData.WorkspacesListWrapper { };
|
||||
workspacesWrapper.Workspaces = new List<ProjectData.ProjectWrapper>();
|
||||
WorkspacesData serializer = new();
|
||||
WorkspacesData.WorkspacesListWrapper workspacesWrapper = new() { };
|
||||
workspacesWrapper.Workspaces = [];
|
||||
|
||||
foreach (Project project in workspaces)
|
||||
{
|
||||
ProjectData.ProjectWrapper wrapper = new ProjectData.ProjectWrapper
|
||||
ProjectData.ProjectWrapper wrapper = new()
|
||||
{
|
||||
Id = project.Id,
|
||||
Name = project.Name,
|
||||
@@ -89,11 +89,11 @@ namespace WorkspacesEditor.Utils
|
||||
IsShortcutNeeded = project.IsShortcutNeeded,
|
||||
MoveExistingWindows = project.MoveExistingWindows,
|
||||
LastLaunchedTime = project.LastLaunchedTime,
|
||||
Applications = new List<ProjectData.ApplicationWrapper> { },
|
||||
MonitorConfiguration = new List<ProjectData.MonitorConfigurationWrapper> { },
|
||||
Applications = [],
|
||||
MonitorConfiguration = [],
|
||||
};
|
||||
|
||||
foreach (var app in project.Applications.Where(x => x.IsIncluded))
|
||||
foreach (Application app in project.Applications.Where(x => x.IsIncluded))
|
||||
{
|
||||
wrapper.Applications.Add(new ProjectData.ApplicationWrapper
|
||||
{
|
||||
@@ -120,7 +120,7 @@ namespace WorkspacesEditor.Utils
|
||||
});
|
||||
}
|
||||
|
||||
foreach (var monitor in project.Monitors)
|
||||
foreach (MonitorSetup monitor in project.Monitors)
|
||||
{
|
||||
wrapper.MonitorConfiguration.Add(new ProjectData.MonitorConfigurationWrapper
|
||||
{
|
||||
@@ -150,7 +150,7 @@ namespace WorkspacesEditor.Utils
|
||||
|
||||
try
|
||||
{
|
||||
IOUtils ioUtils = new IOUtils();
|
||||
IOUtils ioUtils = new();
|
||||
ioUtils.WriteFile(useTempFile ? TempProjectData.File : serializer.File, serializer.Serialize(workspacesWrapper));
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -162,7 +162,7 @@ namespace WorkspacesEditor.Utils
|
||||
|
||||
private bool AddWorkspaces(MainViewModel mainViewModel, WorkspacesData.WorkspacesListWrapper workspaces)
|
||||
{
|
||||
foreach (var project in workspaces.Workspaces)
|
||||
foreach (ProjectData.ProjectWrapper project in workspaces.Workspaces)
|
||||
{
|
||||
mainViewModel.Workspaces.Add(new Project(project));
|
||||
}
|
||||
@@ -173,13 +173,13 @@ namespace WorkspacesEditor.Utils
|
||||
|
||||
private bool SetWorkspaces(MainViewModel mainViewModel, WorkspacesData.WorkspacesListWrapper workspaces)
|
||||
{
|
||||
mainViewModel.Workspaces = new System.Collections.ObjectModel.ObservableCollection<Project> { };
|
||||
mainViewModel.Workspaces = [];
|
||||
return AddWorkspaces(mainViewModel, workspaces);
|
||||
}
|
||||
|
||||
internal void SerializeTempProject(Project project)
|
||||
{
|
||||
SerializeWorkspaces(new List<Project>() { project }, true);
|
||||
SerializeWorkspaces([project], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,24 +156,33 @@
|
||||
Content="{x:Static props:Resources.LaunchAsAdmin}"
|
||||
IsChecked="{Binding IsElevated, Mode=TwoWay}"
|
||||
IsEnabled="{Binding CanLaunchElevated, Mode=OneWay}" />
|
||||
<CheckBox
|
||||
MinWidth="10"
|
||||
Margin="15,0,0,0"
|
||||
Checked="MaximizedChecked"
|
||||
Content="{x:Static props:Resources.Maximized}"
|
||||
IsChecked="{Binding Maximized, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<CheckBox
|
||||
MinWidth="10"
|
||||
Margin="15,0,0,0"
|
||||
Checked="MinimizedChecked"
|
||||
Content="{x:Static props:Resources.Minimized}"
|
||||
IsChecked="{Binding Minimized, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
Margin="100,5,0,0"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
FontWeight="Normal"
|
||||
IsEnabled="{Binding EditPositionEnabled, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Style="{StaticResource TextBlockEnabledStyle}"
|
||||
Text="{x:Static props:Resources.WindowPosition}" />
|
||||
<ComboBox
|
||||
Margin="15,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Background="{DynamicResource SecondaryBackgroundBrush}"
|
||||
BorderBrush="{DynamicResource PrimaryBorderBrush}"
|
||||
BorderThickness="2"
|
||||
FontSize="14"
|
||||
FontWeight="Normal"
|
||||
SelectedIndex="{Binding PositionComboboxIndex, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
|
||||
<ComboBoxItem Content="{x:Static props:Resources.Custom}" />
|
||||
<ComboBoxItem Content="{x:Static props:Resources.Maximized}" />
|
||||
<ComboBoxItem Content="{x:Static props:Resources.Minimized}" />
|
||||
</ComboBox>
|
||||
<TextBlock
|
||||
Margin="15,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
FontWeight="Normal"
|
||||
@@ -267,14 +276,12 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal">
|
||||
<Button
|
||||
Margin="0,20,0,20"
|
||||
Margin="0,10,0,20"
|
||||
VerticalAlignment="Center"
|
||||
Background="Transparent"
|
||||
Click="CancelButtonClicked">
|
||||
@@ -300,27 +307,8 @@
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
Text="{Binding EditorWindowTitle}" />
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="1" Orientation="Vertical">
|
||||
<TextBlock
|
||||
FontSize="14"
|
||||
FontWeight="Normal"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
Text="{x:Static props:Resources.WorkspaceName}" />
|
||||
<TextBox
|
||||
x:Name="EditNameTextBox"
|
||||
Width="320"
|
||||
Margin="0,6,0,6"
|
||||
HorizontalAlignment="Left"
|
||||
Background="{DynamicResource SecondaryBackgroundBrush}"
|
||||
BorderBrush="{DynamicResource PrimaryBorderBrush}"
|
||||
BorderThickness="2"
|
||||
GotFocus="EditNameTextBox_GotFocus"
|
||||
KeyDown="EditNameTextBoxKeyDown"
|
||||
Text="{Binding Name, Mode=TwoWay}"
|
||||
TextChanged="EditNameTextBox_TextChanged" />
|
||||
</StackPanel>
|
||||
<Border
|
||||
Grid.Row="2"
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="{DynamicResource MonitorViewBackgroundBrush}"
|
||||
CornerRadius="5">
|
||||
@@ -361,8 +349,47 @@
|
||||
DockPanel.Dock="Right" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
<DockPanel Grid.Row="2" HorizontalAlignment="Stretch">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBlock
|
||||
Margin="0,10,0,0"
|
||||
FontSize="14"
|
||||
FontWeight="Normal"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
Text="{x:Static props:Resources.WorkspaceName}" />
|
||||
<TextBox
|
||||
x:Name="EditNameTextBox"
|
||||
Width="300"
|
||||
Margin="0,6,0,6"
|
||||
HorizontalAlignment="Left"
|
||||
Background="{DynamicResource SecondaryBackgroundBrush}"
|
||||
BorderBrush="{DynamicResource PrimaryBorderBrush}"
|
||||
BorderThickness="2"
|
||||
GotFocus="EditNameTextBox_GotFocus"
|
||||
KeyDown="EditNameTextBoxKeyDown"
|
||||
Text="{Binding Name, Mode=TwoWay}"
|
||||
TextChanged="EditNameTextBox_TextChanged" />
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
HorizontalAlignment="Right"
|
||||
DockPanel.Dock="Right"
|
||||
Orientation="Horizontal">
|
||||
<CheckBox
|
||||
Margin="20,0,0,0"
|
||||
VerticalAlignment="Bottom"
|
||||
Content="{x:Static props:Resources.CreateShortcut}"
|
||||
FontSize="14"
|
||||
IsChecked="{Binding IsShortcutNeeded, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<CheckBox
|
||||
Margin="20,0,0,0"
|
||||
VerticalAlignment="Bottom"
|
||||
Content="{x:Static props:Resources.MoveIfExist}"
|
||||
FontSize="14"
|
||||
IsChecked="{Binding MoveExistingWindows, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
<ScrollViewer
|
||||
Grid.Row="4"
|
||||
Grid.Row="3"
|
||||
Margin="0,10,0,0"
|
||||
PreviewMouseWheel="ScrollViewer_PreviewMouseWheel"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
@@ -377,52 +404,31 @@
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
<StackPanel
|
||||
Grid.Row="5"
|
||||
Margin="0,5,0,0"
|
||||
Orientation="Horizontal"
|
||||
Visibility="Collapsed">
|
||||
<CheckBox
|
||||
Margin="0,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Content="{x:Static props:Resources.MoveIfExist}"
|
||||
FontSize="14"
|
||||
FontWeight="Normal"
|
||||
Foreground="{DynamicResource PrimaryForegroundBrush}"
|
||||
IsChecked="{Binding MoveExistingWindows, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
|
||||
Grid.Row="4"
|
||||
Margin="40,20,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
x:Name="CancelButton"
|
||||
Height="36"
|
||||
Margin="20,0,0,0"
|
||||
Padding="24,0,24,0"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Cancel}"
|
||||
Background="{DynamicResource SecondaryBackgroundBrush}"
|
||||
BorderBrush="{DynamicResource PrimaryBorderBrush}"
|
||||
BorderThickness="2"
|
||||
Click="CancelButtonClicked"
|
||||
Content="{x:Static props:Resources.Cancel}" />
|
||||
<Button
|
||||
x:Name="SaveButton"
|
||||
Height="36"
|
||||
Margin="20,0,0,0"
|
||||
Padding="24,0,24,0"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Save_Workspace}"
|
||||
Click="SaveButtonClicked"
|
||||
Content="{x:Static props:Resources.Save_Workspace}"
|
||||
IsEnabled="{Binding CanBeSaved, UpdateSourceTrigger=PropertyChanged}"
|
||||
Style="{StaticResource AccentButtonStyle}" />
|
||||
</StackPanel>
|
||||
<DockPanel Grid.Row="6" Margin="0,20,0,20">
|
||||
<CheckBox
|
||||
Content="{x:Static props:Resources.CreateShortcut}"
|
||||
DockPanel.Dock="Left"
|
||||
FontSize="14"
|
||||
IsChecked="{Binding IsShortcutNeeded, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<StackPanel
|
||||
Margin="40,0,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
DockPanel.Dock="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
x:Name="CancelButton"
|
||||
Height="36"
|
||||
Margin="20,0,0,0"
|
||||
Padding="24,0,24,0"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Cancel}"
|
||||
Background="{DynamicResource SecondaryBackgroundBrush}"
|
||||
BorderBrush="{DynamicResource PrimaryBorderBrush}"
|
||||
BorderThickness="2"
|
||||
Click="CancelButtonClicked"
|
||||
Content="{x:Static props:Resources.Cancel}" />
|
||||
<Button
|
||||
x:Name="SaveButton"
|
||||
Height="36"
|
||||
Margin="20,0,0,0"
|
||||
Padding="24,0,24,0"
|
||||
AutomationProperties.Name="{x:Static props:Resources.Save_Workspace}"
|
||||
Click="SaveButtonClicked"
|
||||
Content="{x:Static props:Resources.Save_Workspace}"
|
||||
IsEnabled="{Binding CanBeSaved, UpdateSourceTrigger=PropertyChanged}"
|
||||
Style="{StaticResource AccentButtonStyle}" />
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
</Page>
|
||||
|
||||
@@ -185,20 +185,6 @@ namespace WorkspacesEditor
|
||||
application.CommandLineTextChanged(textBox.Text);
|
||||
}
|
||||
|
||||
private void MaximizedChecked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
CheckBox checkBox = sender as CheckBox;
|
||||
Models.Application application = checkBox.DataContext as Models.Application;
|
||||
application.MaximizedChecked();
|
||||
}
|
||||
|
||||
private void MinimizedChecked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
CheckBox checkBox = sender as CheckBox;
|
||||
Models.Application application = checkBox.DataContext as Models.Application;
|
||||
application.MinimizedChecked();
|
||||
}
|
||||
|
||||
private void LaunchEditButtonClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Button button = sender as Button;
|
||||
|
||||
Reference in New Issue
Block a user