mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-05 02:36:19 +02:00
384 lines
10 KiB
C#
384 lines
10 KiB
C#
// 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.Windows;
|
|
using System.Windows.Controls;
|
|
using FancyZonesEditor.Logs;
|
|
using FancyZonesEditor.Models;
|
|
|
|
namespace FancyZonesEditor
|
|
{
|
|
public class Overlay
|
|
{
|
|
private MainWindow _mainWindow;
|
|
private LayoutPreview _layoutPreview;
|
|
private UserControl _editorLayout;
|
|
private EditorWindow _editorWindow;
|
|
|
|
public List<Monitor> Monitors { get; private set; }
|
|
|
|
public Rect WorkArea
|
|
{
|
|
get
|
|
{
|
|
if (Monitors.Count > 0 && CurrentDesktop < Monitors.Count)
|
|
{
|
|
return Monitors[CurrentDesktop].Device.WorkAreaRect;
|
|
}
|
|
|
|
return default;
|
|
}
|
|
}
|
|
|
|
public LayoutSettings CurrentLayoutSettings
|
|
{
|
|
get
|
|
{
|
|
if (Monitors.Count > 0 && CurrentDesktop < Monitors.Count)
|
|
{
|
|
return Monitors[CurrentDesktop].Settings;
|
|
}
|
|
|
|
return new LayoutSettings();
|
|
}
|
|
}
|
|
|
|
public Window CurrentLayoutWindow
|
|
{
|
|
get
|
|
{
|
|
if (Monitors.Count > 0 && CurrentDesktop < Monitors.Count)
|
|
{
|
|
return Monitors[CurrentDesktop].Window;
|
|
}
|
|
|
|
return default;
|
|
}
|
|
}
|
|
|
|
public List<Rect> WorkAreas { get; private set; }
|
|
|
|
public object CurrentDataContext
|
|
{
|
|
get
|
|
{
|
|
return _dataContext;
|
|
}
|
|
|
|
set
|
|
{
|
|
_dataContext = value;
|
|
CurrentLayoutWindow.DataContext = value;
|
|
}
|
|
}
|
|
|
|
private object _dataContext;
|
|
|
|
public int DesktopsCount
|
|
{
|
|
get
|
|
{
|
|
return Monitors.Count;
|
|
}
|
|
}
|
|
|
|
public int CurrentDesktop
|
|
{
|
|
get
|
|
{
|
|
return _currentDesktop;
|
|
}
|
|
|
|
set
|
|
{
|
|
if (value != _currentDesktop)
|
|
{
|
|
if (value < 0 || value >= DesktopsCount)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_currentDesktop = value;
|
|
|
|
MainWindowSettingsModel settings = ((App)Application.Current).MainWindowSettings;
|
|
if (settings != null)
|
|
{
|
|
settings.SetAppliedModel(null);
|
|
settings.UpdateDefaultModels();
|
|
}
|
|
|
|
Update();
|
|
}
|
|
}
|
|
}
|
|
|
|
private int _currentDesktop;
|
|
|
|
public bool SpanZonesAcrossMonitors { get; set; }
|
|
|
|
public bool MultiMonitorMode
|
|
{
|
|
get
|
|
{
|
|
return DesktopsCount > 1 && !SpanZonesAcrossMonitors;
|
|
}
|
|
}
|
|
|
|
public Overlay()
|
|
{
|
|
WorkAreas = new List<Rect>();
|
|
Monitors = new List<Monitor>();
|
|
}
|
|
|
|
public void Show()
|
|
{
|
|
Logger.LogTrace();
|
|
|
|
var mainWindowSettings = ((App)Application.Current).MainWindowSettings;
|
|
if (_layoutPreview != null)
|
|
{
|
|
mainWindowSettings.PropertyChanged -= _layoutPreview.ZoneSettings_PropertyChanged;
|
|
}
|
|
|
|
_layoutPreview = new LayoutPreview
|
|
{
|
|
IsActualSize = true,
|
|
Opacity = 1,
|
|
};
|
|
|
|
mainWindowSettings.PropertyChanged += _layoutPreview.ZoneSettings_PropertyChanged;
|
|
|
|
ShowLayout();
|
|
OpenMainWindow();
|
|
}
|
|
|
|
public void ShowLayout()
|
|
{
|
|
Logger.LogTrace();
|
|
|
|
MainWindowSettingsModel settings = ((App)Application.Current).MainWindowSettings;
|
|
CurrentDataContext = settings.UpdateSelectedLayoutModel();
|
|
|
|
var window = CurrentLayoutWindow;
|
|
window.Content = _layoutPreview;
|
|
window.DataContext = CurrentDataContext;
|
|
|
|
if (_layoutPreview != null)
|
|
{
|
|
_layoutPreview.UpdatePreview();
|
|
}
|
|
|
|
for (int i = 0; i < DesktopsCount; i++)
|
|
{
|
|
if (!Monitors[i].Window.IsVisible)
|
|
{
|
|
Monitors[i].Window.Show();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SetLayoutSettings(Monitor monitor, LayoutModel model)
|
|
{
|
|
if (model == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
monitor.Settings.ZonesetUuid = model.Uuid;
|
|
monitor.Settings.Type = model.Type;
|
|
monitor.Settings.SensitivityRadius = model.SensitivityRadius;
|
|
monitor.Settings.ZoneCount = model.TemplateZoneCount;
|
|
|
|
if (model is GridLayoutModel grid)
|
|
{
|
|
monitor.Settings.ShowSpacing = grid.ShowSpacing;
|
|
monitor.Settings.Spacing = grid.Spacing;
|
|
}
|
|
else
|
|
{
|
|
monitor.Settings.ShowSpacing = false;
|
|
monitor.Settings.Spacing = 0;
|
|
}
|
|
}
|
|
|
|
public void OpenEditor(LayoutModel model)
|
|
{
|
|
Logger.LogTrace();
|
|
|
|
_layoutPreview = null;
|
|
if (CurrentDataContext is GridLayoutModel)
|
|
{
|
|
_editorLayout = new GridEditor();
|
|
}
|
|
else if (CurrentDataContext is CanvasLayoutModel)
|
|
{
|
|
_editorLayout = new CanvasEditor();
|
|
}
|
|
|
|
CurrentLayoutWindow.Content = _editorLayout;
|
|
|
|
if (model is GridLayoutModel)
|
|
{
|
|
_editorWindow = new GridEditorWindow();
|
|
}
|
|
else
|
|
{
|
|
_editorWindow = new CanvasEditorWindow();
|
|
}
|
|
|
|
_editorWindow.Owner = Monitors[App.Overlay.CurrentDesktop].Window;
|
|
_editorWindow.DataContext = model;
|
|
_editorWindow.Show();
|
|
}
|
|
|
|
public void CloseEditor()
|
|
{
|
|
Logger.LogTrace();
|
|
|
|
var mainWindowSettings = ((App)Application.Current).MainWindowSettings;
|
|
|
|
_editorLayout = null;
|
|
|
|
if (_layoutPreview != null)
|
|
{
|
|
mainWindowSettings.PropertyChanged -= _layoutPreview.ZoneSettings_PropertyChanged;
|
|
}
|
|
|
|
_layoutPreview = new LayoutPreview
|
|
{
|
|
IsActualSize = true,
|
|
Opacity = 1,
|
|
};
|
|
|
|
mainWindowSettings.PropertyChanged += _layoutPreview.ZoneSettings_PropertyChanged;
|
|
|
|
CurrentLayoutWindow.Content = _layoutPreview;
|
|
|
|
OpenMainWindow();
|
|
}
|
|
|
|
public void FocusEditor()
|
|
{
|
|
if (_editorLayout == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (_editorLayout is CanvasEditor canvasEditor)
|
|
{
|
|
canvasEditor.FocusZone();
|
|
}
|
|
else if (_editorLayout is GridEditor gridEditor)
|
|
{
|
|
gridEditor.FocusZone();
|
|
}
|
|
}
|
|
|
|
public void FocusEditorWindow()
|
|
{
|
|
if (_editorWindow != null)
|
|
{
|
|
_editorWindow.Focus();
|
|
}
|
|
}
|
|
|
|
public void CloseLayoutWindow()
|
|
{
|
|
for (int i = 0; i < DesktopsCount; i++)
|
|
{
|
|
Monitors[i].Window.Close();
|
|
}
|
|
}
|
|
|
|
public double ScaleCoordinateWithCurrentMonitorDpi(double coordinate)
|
|
{
|
|
if (Monitors.Count == 0)
|
|
{
|
|
return coordinate;
|
|
}
|
|
|
|
double minimalDpi = Monitors[0].Device.Dpi;
|
|
foreach (Monitor monitor in Monitors)
|
|
{
|
|
if (minimalDpi > monitor.Device.Dpi)
|
|
{
|
|
minimalDpi = monitor.Device.Dpi;
|
|
}
|
|
}
|
|
|
|
if (minimalDpi == 0 || Monitors[CurrentDesktop].Device.Dpi == 0)
|
|
{
|
|
return coordinate;
|
|
}
|
|
|
|
double scaleFactor = minimalDpi / Monitors[CurrentDesktop].Device.Dpi;
|
|
return Math.Round(coordinate * scaleFactor);
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
CloseLayout();
|
|
|
|
if (_mainWindow != null)
|
|
{
|
|
_mainWindow.Update();
|
|
}
|
|
|
|
ShowLayout();
|
|
}
|
|
|
|
private void CloseLayout()
|
|
{
|
|
var window = CurrentLayoutWindow;
|
|
window.Content = null;
|
|
window.DataContext = null;
|
|
}
|
|
|
|
private void OpenMainWindow()
|
|
{
|
|
if (_mainWindow == null)
|
|
{
|
|
_mainWindow = new MainWindow(SpanZonesAcrossMonitors, WorkArea);
|
|
}
|
|
|
|
// reset main window owner to keep it on the top
|
|
_mainWindow.Owner = CurrentLayoutWindow;
|
|
_mainWindow.ShowActivated = true;
|
|
_mainWindow.Topmost = true;
|
|
_mainWindow.Show();
|
|
|
|
// window is set to topmost to make sure it shows on top of PowerToys settings page
|
|
// we can reset topmost flag now
|
|
_mainWindow.Topmost = false;
|
|
}
|
|
|
|
public void AddMonitor(Monitor monitor)
|
|
{
|
|
bool inserted = false;
|
|
var workAreaRect = monitor.Device.WorkAreaRect;
|
|
for (int i = 0; i < Monitors.Count && !inserted; i++)
|
|
{
|
|
var rect = Monitors[i].Device.WorkAreaRect;
|
|
if (workAreaRect.Left < rect.Left && (workAreaRect.Top <= rect.Top || workAreaRect.Top == 0))
|
|
{
|
|
Monitors.Insert(i, monitor);
|
|
inserted = true;
|
|
}
|
|
else if (workAreaRect.Left == rect.Left && workAreaRect.Top < rect.Top)
|
|
{
|
|
Monitors.Insert(i, monitor);
|
|
inserted = true;
|
|
}
|
|
}
|
|
|
|
if (!inserted)
|
|
{
|
|
Monitors.Add(monitor);
|
|
}
|
|
}
|
|
}
|
|
}
|