Merge branch 'develop'

This commit is contained in:
Anton Kasyanov
2016-10-25 20:55:09 +03:00
14 changed files with 533 additions and 296 deletions

View File

@@ -1,188 +1,13 @@
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using Newtonsoft.Json;
namespace EveOPreview.Configuration
namespace EveOPreview.Configuration
{
public class AppConfig : IAppConfig
class AppConfig : IAppConfig
{
public AppConfig()
{
// Default values
this.MinimizeToTray = false;
this.ThumbnailRefreshPeriod = 500;
this.ThumbnailOpacity = 0.5;
this.EnableClientLayoutTracking = false;
this.HideActiveClientThumbnail = false;
this.ShowThumbnailsAlwaysOnTop = true;
this.HideThumbnailsOnLostFocus = false;
this.EnablePerClientThumbnailLayouts = false;
this.ThumbnailSize = new Size(250, 150);
this.ThumbnailMinimumSize = new Size(100, 80);
this.ThumbnailMaximumSize = new Size(640, 400);
this.ThumbnailZoomEnabled = false;
this.ThumbnailZoomFactor = 2;
this.ThumbnailZoomAnchor = ZoomAnchor.NW;
this.ShowThumbnailOverlays = true;
this.ShowThumbnailFrames = true;
this.EnableActiveClientHighlight = false;
this.ActiveClientHighlightColor = Color.Yellow;
this.PerClientLayout = new Dictionary<string, Dictionary<string, Point>>();
this.FlatLayout = new Dictionary<string, Point>();
this.ClientLayout = new Dictionary<string, ClientLayout>();
this.ClientHotkey = new Dictionary<string, string>();
this.ConfigFileName = null;
}
public bool MinimizeToTray { get; set; }
public int ThumbnailRefreshPeriod { get; set; }
[JsonProperty("ThumbnailsOpacity")]
public double ThumbnailOpacity { get; set; }
public bool EnableClientLayoutTracking { get; set; }
public bool HideActiveClientThumbnail { get; set; }
public bool ShowThumbnailsAlwaysOnTop { get; set; }
public bool HideThumbnailsOnLostFocus { get; set; }
public bool EnablePerClientThumbnailLayouts { get; set; }
public Size ThumbnailSize { get; set; }
public Size ThumbnailMaximumSize { get; set; }
public Size ThumbnailMinimumSize { get; set; }
[JsonProperty("EnableThumbnailZoom")]
public bool ThumbnailZoomEnabled { get; set; }
public int ThumbnailZoomFactor { get; set; }
public ZoomAnchor ThumbnailZoomAnchor { get; set; }
public bool ShowThumbnailOverlays { get; set; }
public bool ShowThumbnailFrames { get; set; }
public bool EnableActiveClientHighlight { get; set; }
public Color ActiveClientHighlightColor { get; set; }
[JsonProperty]
private Dictionary<string, Dictionary<string, Point>> PerClientLayout { get; set; }
[JsonProperty]
private Dictionary<string, Point> FlatLayout { get; set; }
[JsonProperty]
private Dictionary<string, ClientLayout> ClientLayout { get; set; }
[JsonProperty]
private Dictionary<string, string> ClientHotkey { get; set; }
public Point GetThumbnailLocation(string currentClient, string activeClient, Point defaultLocation)
{
Dictionary<string, Point> layoutSource = null;
if (this.EnablePerClientThumbnailLayouts)
{
if (!string.IsNullOrEmpty(activeClient))
{
this.PerClientLayout.TryGetValue(activeClient, out layoutSource);
}
}
else
{
layoutSource = this.FlatLayout;
}
if (layoutSource == null)
{
return defaultLocation;
}
Point location;
return layoutSource.TryGetValue(currentClient, out location) ? location : defaultLocation;
}
public void SetThumbnailLocation(string currentClient, string activeClient, Point location)
{
Dictionary<string, Point> layoutSource;
if (this.EnablePerClientThumbnailLayouts)
{
if (string.IsNullOrEmpty(activeClient))
{
return;
}
if (!this.PerClientLayout.TryGetValue(activeClient, out layoutSource))
{
layoutSource = new Dictionary<string, Point>();
this.PerClientLayout[activeClient] = layoutSource;
}
}
else
{
layoutSource = this.FlatLayout;
}
layoutSource[currentClient] = location;
}
public ClientLayout GetClientLayout(string currentClient)
{
ClientLayout layout;
this.ClientLayout.TryGetValue(currentClient, out layout);
return layout;
}
public void SetClientLayout(string currentClient, ClientLayout layout)
{
this.ClientLayout[currentClient] = layout;
}
public Keys GetClientHotkey(string currentClient)
{
string hotkey;
if (this.ClientHotkey.TryGetValue(currentClient, out hotkey))
{
// Protect from incorrect values
object rawValue = (new KeysConverter()).ConvertFromInvariantString(hotkey);
return rawValue != null ? (Keys)rawValue : Keys.None;
}
return Keys.None;
}
public void SetClientHotkey(string currentClient, Keys hotkey)
{
this.ClientHotkey[currentClient] = (new KeysConverter()).ConvertToInvariantString(hotkey);
}
/// <summary>
/// Applies restrictions to different parameters of the config
/// </summary>
public void ApplyRestrictions()
{
this.ThumbnailRefreshPeriod = AppConfig.ApplyRestrictions(this.ThumbnailRefreshPeriod, 300, 1000);
this.ThumbnailSize = new Size(AppConfig.ApplyRestrictions(this.ThumbnailSize.Width, this.ThumbnailMinimumSize.Width, this.ThumbnailMaximumSize.Width),
AppConfig.ApplyRestrictions(this.ThumbnailSize.Height, this.ThumbnailMinimumSize.Height, this.ThumbnailMaximumSize.Height));
this.ThumbnailOpacity = AppConfig.ApplyRestrictions((int)(this.ThumbnailOpacity * 100.00), 20, 100) / 100.00;
this.ThumbnailZoomFactor = AppConfig.ApplyRestrictions(this.ThumbnailZoomFactor, 2, 10);
}
private static int ApplyRestrictions(int value, int minimum, int maximum)
{
if (value <= minimum)
{
return minimum;
}
if (value >= maximum)
{
return maximum;
}
return value;
}
public string ConfigFileName { get; set; }
}
}

View File

@@ -3,37 +3,46 @@ using Newtonsoft.Json;
namespace EveOPreview.Configuration
{
public class ConfigurationStorage : IConfigurationStorage
class ConfigurationStorage : IConfigurationStorage
{
private const string ConfigurationFileName = "EVE-O Preview.json";
private readonly IAppConfig _configuration;
private readonly IAppConfig _appConfig;
private readonly IThumbnailConfig _thumbnailConfig;
public ConfigurationStorage(IAppConfig configuration)
public ConfigurationStorage(IAppConfig appConfig, IThumbnailConfig thumbnailConfig)
{
this._configuration = configuration;
this._appConfig = appConfig;
this._thumbnailConfig = thumbnailConfig;
}
public void Load()
{
if (!File.Exists(ConfigurationStorage.ConfigurationFileName))
string filename = this.GetConfigFileName();
if (!File.Exists(filename))
{
return;
}
string rawData = File.ReadAllText(ConfigurationStorage.ConfigurationFileName);
string rawData = File.ReadAllText(filename);
JsonConvert.PopulateObject(rawData, this._configuration);
JsonConvert.PopulateObject(rawData, this._thumbnailConfig);
// Validate data after loading it
this._configuration.ApplyRestrictions();
this._thumbnailConfig.ApplyRestrictions();
}
public void Save()
{
string rawData = JsonConvert.SerializeObject(this._configuration, Formatting.Indented);
string rawData = JsonConvert.SerializeObject(this._thumbnailConfig, Formatting.Indented);
File.WriteAllText(ConfigurationStorage.ConfigurationFileName, rawData);
File.WriteAllText(this.GetConfigFileName(), rawData);
}
private string GetConfigFileName()
{
return string.IsNullOrEmpty(this._appConfig.ConfigFileName) ? ConfigurationStorage.ConfigurationFileName : this._appConfig.ConfigFileName;
}
}
}

View File

@@ -1,44 +1,10 @@
using System.Drawing;
using System.Windows.Forms;
namespace EveOPreview.Configuration
namespace EveOPreview.Configuration
{
/// <summary>
/// Application configuration
/// </summary>
public interface IAppConfig
{
bool MinimizeToTray { get; set; }
int ThumbnailRefreshPeriod { get; set; }
double ThumbnailOpacity { get; set; }
bool EnableClientLayoutTracking { get; set; }
bool HideActiveClientThumbnail { get; set; }
bool ShowThumbnailsAlwaysOnTop { get; set; }
bool HideThumbnailsOnLostFocus { get; set; }
bool EnablePerClientThumbnailLayouts { get; set; }
Size ThumbnailSize { get; set; }
Size ThumbnailMinimumSize { get; set; }
Size ThumbnailMaximumSize { get; set; }
bool ThumbnailZoomEnabled { get; set; }
int ThumbnailZoomFactor { get; set; }
ZoomAnchor ThumbnailZoomAnchor { get; set; }
bool ShowThumbnailOverlays { get; set; }
bool ShowThumbnailFrames { get; set; }
bool EnableActiveClientHighlight { get; set; }
Color ActiveClientHighlightColor { get; set; }
Point GetThumbnailLocation(string currentClient, string activeClient, Point defaultLocation);
void SetThumbnailLocation(string currentClient, string activeClient, Point location);
ClientLayout GetClientLayout(string currentClient);
void SetClientLayout(string currentClient, ClientLayout layout);
Keys GetClientHotkey(string currentClient);
void SetClientHotkey(string currentClient, Keys hotkey);
void ApplyRestrictions();
string ConfigFileName { get; set; }
}
}

View File

@@ -0,0 +1,48 @@
using System.Drawing;
using System.Windows.Forms;
namespace EveOPreview.Configuration
{
/// <summary>
/// Thumbnails Manager configuration
/// </summary>
public interface IThumbnailConfig
{
bool MinimizeToTray { get; set; }
int ThumbnailRefreshPeriod { get; set; }
double ThumbnailOpacity { get; set; }
bool EnableClientLayoutTracking { get; set; }
bool HideActiveClientThumbnail { get; set; }
bool ShowThumbnailsAlwaysOnTop { get; set; }
bool HideThumbnailsOnLostFocus { get; set; }
bool EnablePerClientThumbnailLayouts { get; set; }
Size ThumbnailSize { get; set; }
Size ThumbnailMinimumSize { get; set; }
Size ThumbnailMaximumSize { get; set; }
bool ThumbnailZoomEnabled { get; set; }
int ThumbnailZoomFactor { get; set; }
ZoomAnchor ThumbnailZoomAnchor { get; set; }
bool ShowThumbnailOverlays { get; set; }
bool ShowThumbnailFrames { get; set; }
bool EnableActiveClientHighlight { get; set; }
Color ActiveClientHighlightColor { get; set; }
int ActiveClientHighlightThickness { get; set; }
Point GetThumbnailLocation(string currentClient, string activeClient, Point defaultLocation);
void SetThumbnailLocation(string currentClient, string activeClient, Point location);
ClientLayout GetClientLayout(string currentClient);
void SetClientLayout(string currentClient, ClientLayout layout);
Keys GetClientHotkey(string currentClient);
void SetClientHotkey(string currentClient, Keys hotkey);
void ApplyRestrictions();
}
}

View File

@@ -0,0 +1,191 @@
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using Newtonsoft.Json;
namespace EveOPreview.Configuration
{
class ThumbnailConfig : IThumbnailConfig
{
public ThumbnailConfig()
{
this.MinimizeToTray = false;
this.ThumbnailRefreshPeriod = 500;
this.ThumbnailOpacity = 0.5;
this.EnableClientLayoutTracking = false;
this.HideActiveClientThumbnail = false;
this.ShowThumbnailsAlwaysOnTop = true;
this.HideThumbnailsOnLostFocus = false;
this.EnablePerClientThumbnailLayouts = false;
this.ThumbnailSize = new Size(250, 150);
this.ThumbnailMinimumSize = new Size(100, 80);
this.ThumbnailMaximumSize = new Size(640, 400);
this.ThumbnailZoomEnabled = false;
this.ThumbnailZoomFactor = 2;
this.ThumbnailZoomAnchor = ZoomAnchor.NW;
this.ShowThumbnailOverlays = true;
this.ShowThumbnailFrames = true;
this.EnableActiveClientHighlight = false;
this.ActiveClientHighlightColor = Color.GreenYellow;
this.ActiveClientHighlightThickness = 3;
this.PerClientLayout = new Dictionary<string, Dictionary<string, Point>>();
this.FlatLayout = new Dictionary<string, Point>();
this.ClientLayout = new Dictionary<string, ClientLayout>();
this.ClientHotkey = new Dictionary<string, string>();
}
public bool MinimizeToTray { get; set; }
public int ThumbnailRefreshPeriod { get; set; }
[JsonProperty("ThumbnailsOpacity")]
public double ThumbnailOpacity { get; set; }
public bool EnableClientLayoutTracking { get; set; }
public bool HideActiveClientThumbnail { get; set; }
public bool ShowThumbnailsAlwaysOnTop { get; set; }
public bool HideThumbnailsOnLostFocus { get; set; }
public bool EnablePerClientThumbnailLayouts { get; set; }
public Size ThumbnailSize { get; set; }
public Size ThumbnailMaximumSize { get; set; }
public Size ThumbnailMinimumSize { get; set; }
[JsonProperty("EnableThumbnailZoom")]
public bool ThumbnailZoomEnabled { get; set; }
public int ThumbnailZoomFactor { get; set; }
public ZoomAnchor ThumbnailZoomAnchor { get; set; }
public bool ShowThumbnailOverlays { get; set; }
public bool ShowThumbnailFrames { get; set; }
public bool EnableActiveClientHighlight { get; set; }
public Color ActiveClientHighlightColor { get; set; }
public int ActiveClientHighlightThickness { get; set; }
[JsonProperty]
private Dictionary<string, Dictionary<string, Point>> PerClientLayout { get; set; }
[JsonProperty]
private Dictionary<string, Point> FlatLayout { get; set; }
[JsonProperty]
private Dictionary<string, ClientLayout> ClientLayout { get; set; }
[JsonProperty]
private Dictionary<string, string> ClientHotkey { get; set; }
public Point GetThumbnailLocation(string currentClient, string activeClient, Point defaultLocation)
{
Point location;
// What this code does:
// If Per-Client layouts are enabled
// and client name is known
// and there is a separate thumbnails layout for this client
// and this layout contains an entry for the current client
// then return that entry
// otherwise try to get client layout from the flat all-clients layout
// If there is no layout too then use the default one
if (this.EnablePerClientThumbnailLayouts && !string.IsNullOrEmpty(activeClient))
{
Dictionary<string, Point> layoutSource;
if (this.PerClientLayout.TryGetValue(activeClient, out layoutSource) && layoutSource.TryGetValue(currentClient, out location))
{
return location;
}
}
return this.FlatLayout.TryGetValue(currentClient, out location) ? location : defaultLocation;
}
public void SetThumbnailLocation(string currentClient, string activeClient, Point location)
{
Dictionary<string, Point> layoutSource;
if (this.EnablePerClientThumbnailLayouts)
{
if (string.IsNullOrEmpty(activeClient))
{
return;
}
if (!this.PerClientLayout.TryGetValue(activeClient, out layoutSource))
{
layoutSource = new Dictionary<string, Point>();
this.PerClientLayout[activeClient] = layoutSource;
}
}
else
{
layoutSource = this.FlatLayout;
}
layoutSource[currentClient] = location;
}
public ClientLayout GetClientLayout(string currentClient)
{
ClientLayout layout;
this.ClientLayout.TryGetValue(currentClient, out layout);
return layout;
}
public void SetClientLayout(string currentClient, ClientLayout layout)
{
this.ClientLayout[currentClient] = layout;
}
public Keys GetClientHotkey(string currentClient)
{
string hotkey;
if (this.ClientHotkey.TryGetValue(currentClient, out hotkey))
{
// Protect from incorrect values
object rawValue = (new KeysConverter()).ConvertFromInvariantString(hotkey);
return rawValue != null ? (Keys)rawValue : Keys.None;
}
return Keys.None;
}
public void SetClientHotkey(string currentClient, Keys hotkey)
{
this.ClientHotkey[currentClient] = (new KeysConverter()).ConvertToInvariantString(hotkey);
}
/// <summary>
/// Applies restrictions to different parameters of the config
/// </summary>
public void ApplyRestrictions()
{
this.ThumbnailRefreshPeriod = ThumbnailConfig.ApplyRestrictions(this.ThumbnailRefreshPeriod, 300, 1000);
this.ThumbnailSize = new Size(ThumbnailConfig.ApplyRestrictions(this.ThumbnailSize.Width, this.ThumbnailMinimumSize.Width, this.ThumbnailMaximumSize.Width),
ThumbnailConfig.ApplyRestrictions(this.ThumbnailSize.Height, this.ThumbnailMinimumSize.Height, this.ThumbnailMaximumSize.Height));
this.ThumbnailOpacity = ThumbnailConfig.ApplyRestrictions((int)(this.ThumbnailOpacity * 100.00), 20, 100) / 100.00;
this.ThumbnailZoomFactor = ThumbnailConfig.ApplyRestrictions(this.ThumbnailZoomFactor, 2, 10);
this.ActiveClientHighlightThickness = ThumbnailConfig.ApplyRestrictions(this.ActiveClientHighlightThickness, 1, 6);
}
private static int ApplyRestrictions(int value, int minimum, int maximum)
{
if (value <= minimum)
{
return minimum;
}
if (value >= maximum)
{
return maximum;
}
return value;
}
}
}

View File

@@ -96,8 +96,10 @@
<Compile Include="ApplicationBase\LightInjectContainer.cs" />
<Compile Include="ApplicationBase\Presenter.cs" />
<Compile Include="ApplicationBase\PresenterGeneric.cs" />
<Compile Include="Configuration\AppConfig.cs" />
<Compile Include="Configuration\ConfigurationStorage.cs" />
<Compile Include="Configuration\IAppConfig.cs" />
<Compile Include="Configuration\IThumbnailConfig.cs" />
<Compile Include="Configuration\ZoomAnchor.cs" />
<Compile Include="DwmAPI\DWM_BLURBEHIND.cs" />
<Compile Include="DwmAPI\DWM_THUMBNAIL_PROPERTIES.cs" />
@@ -118,7 +120,7 @@
<Compile Include="UI\Interface\IThumbnailDescriptionView.cs" />
<Compile Include="UI\Interface\IThumbnailDescriptionViewFactory.cs" />
<Compile Include="UI\Interface\ViewZoomAnchor.cs" />
<Compile Include="Configuration\AppConfig.cs" />
<Compile Include="Configuration\ThumbnailConfig.cs" />
<Compile Include="Hotkeys\HotkeyHandler.cs" />
<Compile Include="Hotkeys\HotkeyHandlerNativeMethods.cs" />
<Compile Include="UI\Implementation\MainForm.cs">

View File

@@ -13,7 +13,7 @@ namespace EveOPreview.UI
#endregion
#region Private fields
private readonly IAppConfig _configuration;
private readonly IThumbnailConfig _configuration;
private readonly IConfigurationStorage _configurationStorage;
private readonly IThumbnailDescriptionViewFactory _thumbnailDescriptionViewFactory;
private readonly IDictionary<IntPtr, IThumbnailDescriptionView> _thumbnailDescriptionViews;
@@ -22,7 +22,7 @@ namespace EveOPreview.UI
private bool _exitApplication;
#endregion
public MainPresenter(IApplicationController controller, IMainView view, IAppConfig configuration, IConfigurationStorage configurationStorage,
public MainPresenter(IApplicationController controller, IMainView view, IThumbnailConfig configuration, IConfigurationStorage configurationStorage,
IThumbnailManager thumbnailManager, IThumbnailDescriptionViewFactory thumbnailDescriptionViewFactory)
: base(controller, view)
{

View File

@@ -15,7 +15,7 @@ namespace EveOPreview.UI
#endregion
#region Private fields
private readonly IAppConfig _configuration;
private readonly IThumbnailConfig _configuration;
private readonly DispatcherTimer _thumbnailUpdateTimer;
private readonly IThumbnailViewFactory _thumbnailViewFactory;
private readonly Dictionary<IntPtr, IThumbnailView> _thumbnailViews;
@@ -27,7 +27,7 @@ namespace EveOPreview.UI
private bool _isHoverEffectActive;
#endregion
public ThumbnailManager(IAppConfig configuration, IThumbnailViewFactory factory)
public ThumbnailManager(IThumbnailConfig configuration, IThumbnailViewFactory factory)
{
this._configuration = configuration;
this._thumbnailViewFactory = factory;
@@ -137,7 +137,8 @@ namespace EveOPreview.UI
view.IsOverlayEnabled = this._configuration.ShowThumbnailOverlays;
view.SetHighlight(this._configuration.EnableActiveClientHighlight && (view.Id == this._activeClientHandle), this._configuration.ActiveClientHighlightColor);
view.SetHighlight(this._configuration.EnableActiveClientHighlight && (view.Id == this._activeClientHandle),
this._configuration.ActiveClientHighlightColor, this._configuration.ActiveClientHighlightThickness);
if (!view.IsActive)
{
@@ -210,11 +211,15 @@ namespace EveOPreview.UI
view = this._thumbnailViewFactory.Create(processHandle, processTitle, this._configuration.ThumbnailSize);
view.IsEnabled = true;
view.IsOverlayEnabled = this._configuration.ShowThumbnailOverlays;
view.SetFrames(this._configuration.ShowThumbnailFrames);
// Max/Min size limitations should be set AFTER the frames are disabled
// Otherwise thumbnail window will be unnecessary resized
view.SetSizeLimitations(this._configuration.ThumbnailMinimumSize, this._configuration.ThumbnailMaximumSize);
view.SetTopMost(this._configuration.ShowThumbnailsAlwaysOnTop);
view.SetFrames(this._configuration.ShowThumbnailFrames);
view.ThumbnailLocation = this._configuration.GetThumbnailLocation(processTitle, this._activeClientTitle, view.ThumbnailLocation);
this._thumbnailViews.Add(processHandle, view);
view.ThumbnailResized = this.ThumbnailViewResized;
view.ThumbnailMoved = this.ThumbnailViewMoved;
view.ThumbnailFocused = this.ThumbnailViewFocused;
@@ -223,8 +228,6 @@ namespace EveOPreview.UI
view.RegisterHotkey(this._configuration.GetClientHotkey(processTitle));
this._thumbnailViews.Add(processHandle, view);
this.ApplyClientLayout(processHandle, processTitle);
viewsAdded.Add(view);

View File

@@ -1,4 +1,5 @@
using System;
using System.Threading;
using System.Windows.Forms;
using EveOPreview.Configuration;
using EveOPreview.UI;
@@ -7,14 +8,99 @@ namespace EveOPreview
{
static class Program
{
private static string MutexName = "EVE-O Preview Single Instance Mutex";
private static string ConfigParameterName = "--config:";
/// <summary>The main entry point for the application.</summary>
[STAThread]
static void Main()
static void Main(string[] args)
{
// The very usual Mutex-based single-instance screening
// 'token' variable is used to store reference to the instance Mutex
// during the app lifetime
object token = Program.GetInstanceToken();
// If it was not possible to aquite the app token then another app instance is already running
// Nothing to do here
if (token == null)
{
return;
}
Program.InitializeWinFormsGui();
IApplicationController controller = Program.InitializeApplicationController();
Program.SetupApplicationConttroller(controller, Program.GetCustomConfigFile(args));
controller.Run<MainPresenter>();
token = null;
}
private static string GetCustomConfigFile(string[] args)
{
// Parse startup parameters
// Simple approach is used because something like NParams would be an overkill here
string configFile = null;
foreach (string arg in args)
{
if ((arg.Length <= Program.ConfigParameterName.Length) || !arg.StartsWith(Program.ConfigParameterName, StringComparison.Ordinal))
{
continue;
}
configFile = arg.Substring(Program.ConfigParameterName.Length);
break;
}
if (string.IsNullOrEmpty(configFile))
{
return "";
}
// One more check to drop trailing "
if ((configFile.Length > 3) && (configFile[0] == '"') && (configFile[configFile.Length - 1] == '"'))
{
configFile = configFile.Substring(1, configFile.Length - 2);
}
return configFile;
}
private static object GetInstanceToken()
{
// The code might look overcomplicated here for a single Mutex operation
// Yet we had already experienced a Windows-level issue
// where .NET finalizer theread was literally paralyzed by
// a failed Mutex operation. That did lead to weird OutOfMemory
// exceptions later
try
{
Mutex mutex = Mutex.OpenExisting(Program.MutexName);
// if that didn't fail then anotherinstance is already running
return null;
}
catch (UnauthorizedAccessException)
{
return null;
}
catch (Exception)
{
bool result;
Mutex token = new Mutex(true, Program.MutexName, out result);
return result ? token : null;
}
}
private static void InitializeWinFormsGui()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
}
// TODO Switch to another container that provides signed assemblies
private static IApplicationController InitializeApplicationController()
{
IIocContainer container = new LightInjectContainer();
// UI classes
@@ -29,9 +115,15 @@ namespace EveOPreview
.RegisterService<IThumbnailViewFactory, ThumbnailViewFactory>()
.RegisterService<IThumbnailDescriptionViewFactory, ThumbnailDescriptionViewFactory>()
.RegisterService<IConfigurationStorage, ConfigurationStorage>()
.RegisterInstance<IAppConfig>(new AppConfig());
.RegisterInstance<IAppConfig>(new AppConfig())
.RegisterInstance<IThumbnailConfig>(new ThumbnailConfig());
controller.Run<MainPresenter>();
return controller;
}
private static void SetupApplicationConttroller(IApplicationController controller, string configFile)
{
controller.Create<IAppConfig>().ConfigFileName = configFile;
}
}
}

View File

@@ -12,7 +12,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("04f08f8d-9e98-423b-acdb-4effb31c0d35")]
[assembly: AssemblyVersion("2.1.0.0")]
[assembly: AssemblyFileVersion("2.1.0.0")]
[assembly: AssemblyVersion("2.2.0.0")]
[assembly: AssemblyFileVersion("2.2.0.0")]
[assembly: CLSCompliant(true)]

View File

@@ -1,5 +1,4 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace EveOPreview.UI
@@ -8,8 +7,6 @@ namespace EveOPreview.UI
{
#region Private fields
private readonly Action<object, MouseEventArgs> _areaClickAction;
private bool _highlightEnabled;
private Color _highlightColor;
#endregion
public ThumbnailOverlay(Form owner, Action<object, MouseEventArgs> areaClickAction)
@@ -17,9 +14,6 @@ namespace EveOPreview.UI
this.Owner = owner;
this._areaClickAction = areaClickAction;
this._highlightEnabled = false;
this._highlightColor = Color.Red;
InitializeComponent();
}
@@ -38,19 +32,6 @@ namespace EveOPreview.UI
this.OverlayLabel.Visible = enable;
}
public void EnableHighlight(bool enabled, Color color)
{
if (enabled == this._highlightEnabled)
{
// Nothing to do here
return;
}
this._highlightEnabled = enabled;
this._highlightColor = color;
this.Refresh();
}
protected override CreateParams CreateParams
{
get
@@ -60,19 +41,5 @@ namespace EveOPreview.UI
return Params;
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (this._highlightEnabled)
{
ControlPaint.DrawBorder(e.Graphics, this.ClientRectangle,
this._highlightColor, 4, ButtonBorderStyle.Solid,
this._highlightColor, 4, ButtonBorderStyle.Solid,
this._highlightColor, 4, ButtonBorderStyle.Solid,
this._highlightColor, 4, ButtonBorderStyle.Solid);
}
}
}
}

View File

@@ -18,6 +18,8 @@ namespace EveOPreview.UI
private bool _isPositionChanged;
private bool _isSizeChanged;
private bool _isCustomMouseModeActive;
private bool _isHighlightEnabled;
private int _highlightWidth;
private DateTime _suppressResizeEventsTimestamp;
private DWM_THUMBNAIL_PROPERTIES _thumbnail;
private IntPtr _thumbnailHandle;
@@ -43,6 +45,8 @@ namespace EveOPreview.UI
this._isSizeChanged = true;
this._isCustomMouseModeActive = false;
this._isHighlightEnabled = false;
this._suppressResizeEventsTimestamp = DateTime.UtcNow;
InitializeComponent();
@@ -197,9 +201,26 @@ namespace EveOPreview.UI
this._isTopMost = enableTopmost;
}
public void SetHighlight(bool enabled, Color color)
public void SetHighlight(bool enabled, Color color, int width)
{
this._overlay.EnableHighlight(enabled, color);
if (this._isHighlightEnabled == enabled)
{
return;
}
if (enabled)
{
this._isHighlightEnabled = true;
this._highlightWidth = width;
this.BackColor = color;
}
else
{
this._isHighlightEnabled = false;
this.BackColor = SystemColors.Control;
}
this._isSizeChanged = true;
}
public void ZoomIn(ViewZoomAnchor anchor, int zoomFactor)
@@ -310,7 +331,29 @@ namespace EveOPreview.UI
if (sizeChanged)
{
this._thumbnail.rcDestination = new RECT(0, 0, this.ClientSize.Width, this.ClientSize.Height);
// This approach would work only for square-shaped thumbnail window
// To get PROPER results we have to do some crazy math
//int delta = this._isHighlightEnabled ? this._highlightWidth : 0;
//this._thumbnail.rcDestination = new RECT(0 + delta, 0 + delta, this.ClientSize.Width - delta, this.ClientSize.Height - delta);
if (this._isHighlightEnabled)
{
int baseWidth = this.ClientSize.Width;
int baseHeight = this.ClientSize.Height;
double baseAspectRatio = ((double)baseWidth) / baseHeight;
int actualHeight = baseHeight - 2 * this._highlightWidth;
double desiredWidth = actualHeight * baseAspectRatio;
int actualWidth = (int)Math.Round(desiredWidth, MidpointRounding.AwayFromZero);
int highlightWidthLeft = (baseWidth - actualWidth) / 2;
int highlightWidthRight = baseWidth - actualWidth - highlightWidthLeft;
this._thumbnail.rcDestination = new RECT(0 + highlightWidthLeft, 0 + this._highlightWidth, baseWidth - highlightWidthRight, baseHeight - this._highlightWidth);
}
else
{
//No highlighting enables, so no odd math required
this._thumbnail.rcDestination = new RECT(0, 0, this.ClientSize.Width, this.ClientSize.Height);
}
try
{
WindowManagerNativeMethods.DwmUpdateThumbnailProperties(this._thumbnailHandle, this._thumbnail);
@@ -348,8 +391,9 @@ namespace EveOPreview.UI
Size overlaySize = this.ClientSize;
Point overlayLocation = this.Location;
overlayLocation.X += (this.Size.Width - this.ClientSize.Width) / 2;
overlayLocation.Y += (this.Size.Height - this.ClientSize.Height) - (this.Size.Width - this.ClientSize.Width) / 2;
int borderWidth = (this.Size.Width - this.ClientSize.Width) / 2;
overlayLocation.X += borderWidth;
overlayLocation.Y += (this.Size.Height - this.ClientSize.Height) - borderWidth;
this._isPositionChanged = false;
this._overlay.Size = overlaySize;

View File

@@ -21,7 +21,7 @@ namespace EveOPreview.UI
void SetOpacity(double opacity);
void SetFrames(bool enable);
void SetTopMost(bool enableTopmost);
void SetHighlight(bool enabled, Color color);
void SetHighlight(bool enabled, Color color, int width);
void ZoomIn(ViewZoomAnchor anchor, int zoomFactor);
void ZoomOut();

120
README.md
View File

@@ -1,4 +1,6 @@
The purpose of this tool is to provide a simple way to keep an eye on several simultaneously running EVE Online clients and to easily switch between them. While running it shows a set of live thumbnails for each of the active EVE Online clients. These thumbnails allow fast switch to the corresponding EVE Online client either using mouse or a configurable hotkey.
#Overview
The purpose of this application is to provide a simple way to keep an eye on several simultaneously running EVE Online clients and to easily switch between them. While running it shows a set of live thumbnails for each of the active EVE Online clients. These thumbnails allow fast switch to the corresponding EVE Online client either using mouse or a configurable hotkey.
It's essentially a task switcher, it does not relay any keyboard/mouse events and suchlike. The app works with EVE, EVE through Steam, or any combination thereof.
@@ -8,22 +10,25 @@ The program does NOT (and will NOT ever) do the following things:
* broadcast any keyboard or mouse events
* anyhow interact with EVE Online except of bringing its main window to foreground or resizing it
Under any conditions you should NOT use EVE-O Preview for any actions that break EULA or ToS of EVE Online.
**System Requirements**
If you have find out that some of the features or their combination of EVE-O Preview might cause actions that can be considered as breaking EULA or ToS of EVE Online you should consider them as a bug and immediately notify the Developer ( Phrynohyas Tig-Rah ) via in-game mail.
#System Requirements
* Windows Vista, Windows 7, Windows 8/8.1, Windows 10
* Windows Aero Enabled
* Microsoft .NET Framework 4.5+
**How To Install & Use**
#How To Install & Use
1. Download and extract the contents of the .zip archive to a location of your choice (ie: Desktop, CCP folder, etc)
..* **Note**: Please do not install the program into the *Program Files* or *Program files (x86)* folders. These folders in general do not allow applications to write anything there while EVE-O Preview now stores its configuration file next to its executable, thus requiring the write access to the folder it is installed into.
2. Start up both EVE-O Preview and your EVE Clients (the order does not matter)
3. Adjust settings as you see fit. Program options are described [here](https://github.com/Phrynohyas/eve-o-preview/wiki/EVE-O-Preview-Program-Options)
3. Adjust settings as you see fit. Program options are described below
***
#EVE Online EULA/ToS
This program is legal under the EULA/ToS:
@@ -39,31 +44,116 @@ CCP FoxFour wrote:
> to bring the respective EVE Client to the front/put the window focus on it, in order to
> interact with it.
***
#Application Options
**Created by**
##Startup Parameters
| Parameter | Description |
| --- | --- |
| **config** | This option allows to start the application with a custom configuration file. If the provided file doesn't exists it will be created with default values.<br />For example **"Eve-O&nbsp;Preview.exe"&nbsp;--config:TestSetup.json** |
##Application Options Available Via GUI
| Option | Description |
| --- | --- |
| Minimize to System Tray | Determines whether the main window form be minimized to windows tray when it is closed |
| Opacity | Determines the inactive EVE thumbnails opacity (from almost invisible 20% to 100% solid) |
| Track client locations | Determines whether the client's window position should be restored when it is activated or started |
| Hide preview of active EVE client | Determines whether the thumbnail corresponding to the active EVE client is not displayed |
| Previews always on top | Determines whether EVE client thumbnails should stay on top of all other windows |
| Hide previews when EVE client is not active | Determines whether all thumbnails should be visible only when an EVE client is active |
| Unique layout for each EVE client | Determines whether thumbnails positions are different depending on the EVE client being active (f.e. links char have thumbnails of the Falcon and DPS char in the right bottom corner while DPS and Falcon alts have them placed at the top of the main EVE window ) |
| Thumbnail width | Thumbnails width. Can be set to any value from **100** to **640** points |
| Thumbnail height | Thumbnails Height. Can be set to any value from **80** to **400** points |
| Zoom on hover | Determines whether a thumbnail should be zoomed when the mouse pointer is over it |
| Zoom factor | Thumbnail zoom factor. Can be set to any value from **2** to **10** |
| Zoom anchor | Sets the starting point of the thumbnail zoom |
| Show overlay | Determines whether a name of the corresponding EVE cliet should be displayed on the thumbnail |
| Show frames | Determines whether thumbnails should be displayd with window caption and borders |
| Highlight active client | Determines whether the thumbnail of the active EVE client should be highlighted with a bright border |
| Color | Color used to highlight the active client's thumbnail in case the corresponding option is set |
| Thumbnails list | List of currently active EVE client thumbnails. Checking an element in this list will hide the corresponding thumbnail. However these checks are not persisted and on the next EVE client or EVE-O Preview run the thumbnail will be visible again |
##Mouse Gestures
Mouse gestures are applied to the thumbnail window currently being hovered over.
| Action | Gesture |
| --- | --- |
| Move thumbnail to a new position | Press right mouse button and move the mouse |
| Adjust thumbnail height | Press both left and right mouse buttons and move the mouse up or down |
| Adjust thumbnail width | Press both left and right mouse buttons and move the mouse left or right |
##Configuration File-Only Options
Some of the application options are not exposed in the GUI. They can be ajusted directly in the configuration file.
**Note:** Do any changes to the configuration file only while the EVE-O Preview itself is closed. Otherwise the changes you made might be lost.
| Option | Description |
| --- | --- |
| **ActiveClientHighlightThickness** | Thickness of the border used to highlight the active client's thumbnail.<br />Allowed values are **1**...**6**.<br />The default value is **3**<br />For example: **"ActiveClientHighlightThickness": 3,** |
| **ThumbnailMinimumSize** | Minimum thumbnail size that can be set either via GUI or by resizing a thumbnail window. Value is witten in the form "width, height"<br />The default value is **"100, 80"**.<br />For example: **"ThumbnailMinimumSize": "100, 80",** |
| **ThumbnailMaximumSize** | Maximum thumbnail size that can be set either via GUI or by resizing a thumbnail window. Value is witten in the form "width, height"<br />The default value is **"640, 400"**.<br />For example: **"ThumbnailMaximumSize": "640, 400",** |
##Hotkey Setup
It is possible to set a key kombinations to immediately jump to cetrain EVE window. However currently EVE-O Preview doesn't provide any GUI to set the these hotkeys. It should be done via editind the configuration file directly. Don't forget to make a backup copy of the file before editing it.
**Note**: Don't forget to make a backup copy of the file before editing it.
Open the file using any text editor. find the entry **ClientHotkey**. Most probably it will look like
"ClientHotkey": {},
This means that no hotkeys are defined. Edit it to be like
"ClientHotkey": {
"EVE - Phrynohyas Tig-Rah": "F1",
"EVE - Ondatra Patrouette": "F2"
}
This simple edit will assign **F1** as a hotkey for Phrynohyas Tig-Rah and **F2** as a hotkey for Ondatra Patrouette, so pressing F1 anywhere in Windows will immediately open EVE client for Phrynohyas Tig-Rah if he is logged on.
The following hotkey is described as `modifier+key` where `modifier` can be **Control**, **Alt**, **Shift**, or their combination. F.e. it is possible to setup the hotkey as
"ClientHotkey": {
"EVE - Phrynohyas Tig-Rah": "F1",
"EVE - Ondatra Patrouette": "Control+Shift+F4"
}
**Note:** Do not set hotkeys to use the key combinations already used by EVE. It won't work as "_I set hotkey for my DPS char to F1 and when I'll press F1 it will automatically open the DPS char's window and activate guns_". Key combination will be swallowed by EVE-O Preview and NOT retranslated to EVE window. So it will be only "_it will automatically open the DPS char's window_".
---
#Credits
##Created by
* StinkRay
**Maintained by**
* StinkRay
* Makari Aeron
##Maintained by
* Phrynohyas Tig-Rah
* Makari Aeron
**With contributions from**
* StinkRay
##With contributions from
* CCP FoxFour
**Original threads**
##Original threads
https://forums.eveonline.com/default.aspx?g=posts&t=389086
https://forums.eveonline.com/default.aspx?g=posts&t=246157
**Original repository**
##Original repository
https://bitbucket.org/ulph/eve-o-preview-git