Adding per client borders and hotkey to cycle through clients

This commit is contained in:
Aura Asuna
2022-05-10 01:31:50 +10:00
parent f5777de77c
commit 0ddaa99c9a
12 changed files with 317 additions and 17 deletions

View File

@@ -27,7 +27,14 @@ namespace EveOPreview.Configuration.Implementation
string rawData = File.ReadAllText(filename);
JsonConvert.PopulateObject(rawData, this._thumbnailConfiguration);
JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings()
{
ObjectCreationHandling = ObjectCreationHandling.Replace
};
// StageHotkeyArraysToAvoidDuplicates(rawData);
JsonConvert.PopulateObject(rawData, this._thumbnailConfiguration, jsonSerializerSettings);
// Validate data after loading it
this._thumbnailConfiguration.ApplyRestrictions();

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using Newtonsoft.Json;
@@ -14,6 +15,30 @@ namespace EveOPreview.Configuration.Implementation
public ThumbnailConfiguration()
{
this.CycleGroup1ForwardHotkeys = new List<string> { "F14", "Control+F14" };
this.CycleGroup1BackwardHotkeys = new List<string> { "F13", "Control+F13" };
this.CycleGroup1ClientsOrder = new Dictionary<string, string>
{
{ "EVE - Example DPS Toon 1", "1" },
{ "EVE - Example DPS Toon 2", "2" },
{ "EVE - Example DPS Toon 3", "3" }
};
this.CycleGroup2ForwardHotkeys = new List<string> { "F16", "Control+F16" };
this.CycleGroup2BackwardHotkeys = new List<string> { "F15", "Control+F15" };
this.CycleGroup2ClientsOrder = new Dictionary<string, string>
{
{ "EVE - Example Logi Toon 1", "1" },
{ "EVE - Example Scout Toon 2", "2" },
{ "EVE - Example Tackle Toon 3", "3" }
};
this.PerClientActiveClientHighlightColor = new Dictionary<string, Color>
{
{"EVE - Example Toon 1", Color.Red},
{"EVE - Example Toon 2", Color.Green}
};
this.PerClientLayout = new Dictionary<string, Dictionary<string, Point>>();
this.FlatLayout = new Dictionary<string, Point>();
this.ClientLayout = new Dictionary<string, ClientLayout>();
@@ -55,6 +80,27 @@ namespace EveOPreview.Configuration.Implementation
this.ActiveClientHighlightThickness = 3;
}
[JsonProperty("CycleGroup1ForwardHotkeys")]
public List<string> CycleGroup1ForwardHotkeys { get; set; }
[JsonProperty("CycleGroup1BackwardHotkeys")]
public List<string> CycleGroup1BackwardHotkeys { get; set; }
[JsonProperty("CycleGroup1ClientsOrder")]
public Dictionary<string, string> CycleGroup1ClientsOrder { get; set; }
[JsonProperty("CycleGroup2ForwardHotkeys")]
public List<string> CycleGroup2ForwardHotkeys { get; set; }
[JsonProperty("CycleGroup2BackwardHotkeys")]
public List<string> CycleGroup2BackwardHotkeys { get; set; }
[JsonProperty("CycleGroup2ClientsOrder")]
public Dictionary<string, string> CycleGroup2ClientsOrder { get; set; }
[JsonProperty("PerClientActiveClientHighlightColor")]
public Dictionary<string, Color> PerClientActiveClientHighlightColor { get; set; }
public bool MinimizeToTray { get; set; }
public int ThumbnailRefreshPeriod { get; set; }
@@ -220,6 +266,12 @@ namespace EveOPreview.Configuration.Implementation
this.ClientHotkey[currentClient] = (new KeysConverter()).ConvertToInvariantString(hotkey);
}
public Keys StringToKey(string hotkey)
{
object rawValue = (new KeysConverter()).ConvertFromInvariantString(hotkey);
return rawValue != null ? (Keys)rawValue : Keys.None;
}
public bool IsPriorityClient(string currentClient)
{
return this.PriorityClients.Contains(currentClient);

View File

@@ -1,10 +1,21 @@
using System.Drawing;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace EveOPreview.Configuration
{
public interface IThumbnailConfiguration
{
List<string> CycleGroup1ForwardHotkeys { get; set; }
List<string> CycleGroup1BackwardHotkeys { get; set; }
Dictionary<string, string> CycleGroup1ClientsOrder { get; set; }
List<string> CycleGroup2ForwardHotkeys { get; set; }
List<string> CycleGroup2BackwardHotkeys { get; set; }
Dictionary<string, string> CycleGroup2ClientsOrder { get; set; }
Dictionary<string, Color> PerClientActiveClientHighlightColor { get; set; }
bool MinimizeToTray { get; set; }
int ThumbnailRefreshPeriod { get; set; }
@@ -47,6 +58,7 @@ namespace EveOPreview.Configuration
Keys GetClientHotkey(string currentClient);
void SetClientHotkey(string currentClient, Keys hotkey);
Keys StringToKey(string hotkey);
bool IsPriorityClient(string currentClient);

View File

@@ -1,10 +1,14 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Threading;
using EveOPreview.Configuration;
using EveOPreview.Mediator.Messages;
using EveOPreview.UI.Hotkeys;
using EveOPreview.View;
using MediatR;
@@ -42,6 +46,8 @@ namespace EveOPreview.Services
private int _refreshCycleCount;
private int _hideThumbnailsDelay;
private List<HotkeyHandler> _cycleClientHotkeyHandlers = new List<HotkeyHandler>();
#endregion
public ThumbnailManager(IMediator mediator, IThumbnailConfiguration configuration, IProcessMonitor processMonitor, IWindowManager windowManager, IThumbnailViewFactory factory)
@@ -69,6 +75,109 @@ namespace EveOPreview.Services
this._thumbnailUpdateTimer.Interval = new TimeSpan(0, 0, 0, 0, configuration.ThumbnailRefreshPeriod);
this._hideThumbnailsDelay = this._configuration.HideThumbnailsDelay;
RegisterCycleClientHotkey(this._configuration.CycleGroup1ForwardHotkeys?.Select(x => this._configuration.StringToKey(x)), true, this._configuration.CycleGroup1ClientsOrder);
RegisterCycleClientHotkey(this._configuration.CycleGroup1BackwardHotkeys?.Select(x => this._configuration.StringToKey(x)), false, this._configuration.CycleGroup1ClientsOrder);
RegisterCycleClientHotkey(this._configuration.CycleGroup2ForwardHotkeys?.Select(x => this._configuration.StringToKey(x)), true, this._configuration.CycleGroup2ClientsOrder);
RegisterCycleClientHotkey(this._configuration.CycleGroup2BackwardHotkeys?.Select(x => this._configuration.StringToKey(x)), false, this._configuration.CycleGroup2ClientsOrder);
}
public IThumbnailView GetClientByTitle(string title)
{
return _thumbnailViews.FirstOrDefault(x => x.Value.Title == title).Value;
}
public IThumbnailView GetClientByPointer(IntPtr ptr)
{
return _thumbnailViews.FirstOrDefault(x => x.Key == ptr).Value;
}
public IThumbnailView GetActiveClient()
{
return GetClientByPointer(this._activeClient.Handle);
}
public void SetActive(KeyValuePair<IntPtr, IThumbnailView> newClient)
{
this.GetActiveClient()?.ClearBorder();
this._windowManager.ActivateWindow(newClient.Key);
this.SwitchActiveClient(newClient.Key, newClient.Value.Title);
newClient.Value.SetHighlight();
newClient.Value.Refresh(true);
}
public void CycleNextClient(bool isForwards, Dictionary<string, string> cycleOrder)
{
IOrderedEnumerable<KeyValuePair<string, string>> clientOrder;
if (isForwards)
{
clientOrder = cycleOrder.OrderBy(x => x.Value);
}
else
{
clientOrder = cycleOrder.OrderByDescending(x => x.Value);
}
bool setNextClient = false;
IThumbnailView lastClient = null;
foreach (var t in clientOrder)
{
if (t.Key == _activeClient.Title)
{
setNextClient = true;
lastClient = _thumbnailViews.FirstOrDefault(x => x.Value.Title == t.Key).Value;
continue;
}
if (!setNextClient)
{
continue;
}
if (_thumbnailViews.Any(x => x.Value.Title == t.Key))
{
var ptr = _thumbnailViews.First(x => x.Value.Title == t.Key);
SetActive(ptr);
return;
}
}
// we didn't get a next one. just get the first one from the start.
foreach (var t in clientOrder)
{
if (_thumbnailViews.Any(x => x.Value.Title == t.Key))
{
var ptr = _thumbnailViews.First(x => x.Value.Title == t.Key);
SetActive(ptr);
_activeClient = (ptr.Key, t.Key);
return;
}
}
}
public void RegisterCycleClientHotkey(IEnumerable<Keys> keys, bool isForwards, Dictionary<string, string> cycleOrder)
{
foreach (var hotkey in keys)
{
if (hotkey == Keys.None)
{
return;
}
var newHandler = new HotkeyHandler(default(IntPtr), hotkey);
newHandler.Pressed += (object s, HandledEventArgs e) =>
{
this.CycleNextClient(isForwards, cycleOrder);
e.Handled = true;
};
newHandler.Register();
this._cycleClientHotkeyHandlers.Add(newHandler);
}
}
public void Start()
@@ -306,8 +415,9 @@ namespace EveOPreview.Services
view.IsOverlayEnabled = this._configuration.ShowThumbnailOverlays;
view.SetHighlight(this._configuration.EnableActiveClientHighlight && (view.Id == this._activeClient.Handle),
this._configuration.ActiveClientHighlightColor, this._configuration.ActiveClientHighlightThickness);
view.SetHighlight(
this._configuration.EnableActiveClientHighlight && (view.Id == this._activeClient.Handle),
this._configuration.ActiveClientHighlightThickness);
if (!view.IsActive)
{

View File

@@ -5,7 +5,7 @@ using EveOPreview.Services.Interop;
namespace EveOPreview.Services.Implementation
{
sealed class WindowManager : IWindowManager
public class WindowManager : IWindowManager
{
#region Private constants
private const int WINDOW_SIZE_THRESHOLD = 300;
@@ -30,6 +30,7 @@ namespace EveOPreview.Services.Implementation
public void ActivateWindow(IntPtr handle)
{
User32NativeMethods.SetForegroundWindow(handle);
User32NativeMethods.SetFocus(handle);
int style = User32NativeMethods.GetWindowLong(handle, InteropConstants.GWL_STYLE);

View File

@@ -1,4 +1,6 @@
namespace EveOPreview.Services
using EveOPreview.View;
namespace EveOPreview.Services
{
public interface IThumbnailManager
{
@@ -7,5 +9,9 @@
void UpdateThumbnailsSize();
void UpdateThumbnailFrames();
IThumbnailView GetClientByTitle(string title);
IThumbnailView GetClientByPointer(System.IntPtr ptr);
IThumbnailView GetActiveClient();
}
}

View File

@@ -11,6 +11,12 @@ namespace EveOPreview.Services.Interop
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr window);
[DllImport("user32.dll")]
public static extern void SetFocus(IntPtr window);
[DllImport("user32.dll")]
public static extern void EnableWindow(IntPtr window, bool isEnabled);
[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);

View File

@@ -1,5 +1,6 @@
using System;
using System.Drawing;
using EveOPreview.Configuration;
using EveOPreview.Services;
namespace EveOPreview.View
@@ -10,13 +11,15 @@ namespace EveOPreview.View
private IDwmThumbnail _thumbnail;
private Point _startLocation;
private Point _endLocation;
private IThumbnailConfiguration _config;
#endregion
public LiveThumbnailView(IWindowManager windowManager)
: base(windowManager)
public LiveThumbnailView(IWindowManager windowManager, IThumbnailConfiguration config, IThumbnailManager thumbnailManager)
: base(windowManager, config, thumbnailManager)
{
this._startLocation = new Point(0, 0);
this._endLocation = new Point(this.ClientSize);
this._config = config;
}
protected override void RefreshThumbnail(bool forceRefresh)

View File

@@ -1,6 +1,7 @@
using System;
using System.Drawing;
using System.Windows.Forms;
using EveOPreview.Configuration;
using EveOPreview.Services;
namespace EveOPreview.View
@@ -9,10 +10,11 @@ namespace EveOPreview.View
{
#region Private fields
private readonly PictureBox _thumbnail;
private IThumbnailConfiguration _config;
#endregion
public StaticThumbnailView(IWindowManager windowManager)
: base(windowManager)
public StaticThumbnailView(IWindowManager windowManager, IThumbnailConfiguration config, IThumbnailManager thumbnailManager)
: base(windowManager, config, thumbnailManager)
{
this._thumbnail = new StaticThumbnailImage
{
@@ -22,6 +24,7 @@ namespace EveOPreview.View
Size = new Size(this.ClientSize.Width, this.ClientSize.Height)
};
this.Controls.Add(this._thumbnail);
this._config = config;
}
protected override void RefreshThumbnail(bool forceRefresh)

View File

@@ -1,7 +1,9 @@
using System;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using EveOPreview.Configuration;
using EveOPreview.Services;
using EveOPreview.UI.Hotkeys;
@@ -40,9 +42,13 @@ namespace EveOPreview.View
private Size _baseZoomMaximumSize;
private HotkeyHandler _hotkeyHandler;
private IThumbnailConfiguration _config;
private Lazy<Color> _myBorderColor;
private IThumbnailManager _thumbnailManager;
#endregion
protected ThumbnailView(IWindowManager windowManager)
protected ThumbnailView(IWindowManager windowManager, IThumbnailConfiguration config, IThumbnailManager thumbnailManager)
{
this.SuppressResizeEvent();
@@ -66,9 +72,13 @@ namespace EveOPreview.View
InitializeComponent();
this._overlay = new ThumbnailOverlay(this, this.MouseDown_Handler);
this._config = config;
SetDefaultBorderColor();
this._thumbnailManager = thumbnailManager;
}
protected IWindowManager WindowManager { get; }
public IWindowManager WindowManager { get; }
public IntPtr Id { get; set; }
@@ -78,14 +88,15 @@ namespace EveOPreview.View
set
{
this.Text = value;
this._overlay.SetOverlayLabel(value);
this._overlay.SetOverlayLabel(value.Replace("EVE - ", ""));
SetDefaultBorderColor();
}
}
public bool IsActive { get; set; }
public bool IsOverlayEnabled { get; set; }
public Point ThumbnailLocation
{
get => this.Location;
@@ -114,6 +125,21 @@ namespace EveOPreview.View
public Action<IntPtr, bool> ThumbnailDeactivated { get; set; }
public void SetDefaultBorderColor()
{
this._myBorderColor = new Lazy<Color>(() =>
{
if (this._config.PerClientActiveClientHighlightColor.Any(x => x.Key == this.Title))
{
return this._config.PerClientActiveClientHighlightColor[Title];
}
else
{
return _config.ActiveClientHighlightColor;
}
});
}
public new void Show()
{
this.SuppressResizeEvent();
@@ -219,7 +245,12 @@ namespace EveOPreview.View
this._isTopMost = enableTopmost;
}
public void SetHighlight(bool enabled, Color color, int width)
public void SetHighlight()
{
SetHighlight(_config.EnableActiveClientHighlight, _config.ActiveClientHighlightThickness);
}
public void SetHighlight(bool enabled, int width)
{
if (this._isHighlightRequested == enabled)
{
@@ -230,7 +261,7 @@ namespace EveOPreview.View
{
this._isHighlightRequested = true;
this._highlightWidth = width;
this.BackColor = color;
this.BackColor = _myBorderColor.Value;
}
else
{
@@ -241,6 +272,12 @@ namespace EveOPreview.View
this._isSizeChanged = true;
}
public void ClearBorder()
{
this.SetHighlight(false, 0);
this.Refresh(true);
}
public void ZoomIn(ViewZoomAnchor anchor, int zoomFactor)
{
int oldWidth = this._baseZoomSize.Width;
@@ -475,6 +512,7 @@ namespace EveOPreview.View
private void HotkeyPressed_Handler(object sender, HandledEventArgs e)
{
this.SetHighlight();
this.ThumbnailActivated?.Invoke(this.Id);
e.Handled = true;
@@ -549,7 +587,12 @@ namespace EveOPreview.View
this.ThumbnailDeactivated?.Invoke(this.Id, true);
break;
case MouseButtons.Left:
var oldWindow = this._thumbnailManager.GetActiveClient();
this.ThumbnailActivated?.Invoke(this.Id);
this.SetHighlight();
this.Refresh(true);
oldWindow?.ClearBorder();
break;
case MouseButtons.Right:
case MouseButtons.Left | MouseButtons.Right:

View File

@@ -1,6 +1,7 @@
using System;
using System.Drawing;
using System.Windows.Forms;
using EveOPreview.Services;
namespace EveOPreview.View
{
@@ -20,7 +21,8 @@ namespace EveOPreview.View
void SetOpacity(double opacity);
void SetFrames(bool enable);
void SetTopMost(bool enableTopmost);
void SetHighlight(bool enabled, Color color, int width);
void SetHighlight();
void SetHighlight(bool enabled, int width);
void ZoomIn(ViewZoomAnchor anchor, int zoomFactor);
void ZoomOut();
@@ -37,5 +39,9 @@ namespace EveOPreview.View
Action<IntPtr> ThumbnailActivated { get; set; }
Action<IntPtr, bool> ThumbnailDeactivated { get; set; }
IWindowManager WindowManager { get; }
void SetDefaultBorderColor();
void ClearBorder();
}
}