5 Commits

Author SHA1 Message Date
6a128ef899 Update 2026-01-17 12:38:01 +01:00
2ae6a90117 Update configs 2026-01-17 12:33:05 +01:00
1b334edaf7 Add profiles 2026-01-17 12:27:26 +01:00
0a920a0c8d Implement a simple profile manager and allow for switching between
profiles via tray icon
2026-01-17 12:27:16 +01:00
b50491a08d Fix issue where hiding thumbnails was delayed 2026-01-16 23:35:50 +01:00
14 changed files with 880 additions and 18 deletions

View File

@@ -0,0 +1,3 @@
{
"ActiveProfile": "Default"
}

View File

@@ -80,7 +80,7 @@
"EnablePerClientThumbnailLayouts": false,
"HideThumbnailsOnLostFocus": false,
"HideThumbnailsDelay": 2,
"ThumbnailSize": "451, 388",
"ThumbnailSize": "512, 288",
"ThumbnailMaximumSize": "960, 540",
"ThumbnailMinimumSize": "192, 108",
"EnableThumbnailSnap": true,
@@ -93,14 +93,14 @@
"ShowThumbnailFrames": false,
"LockThumbnailLocation": false,
"ThumbnailSnapToGrid": true,
"ThumbnailSnapToGridSizeX": 112,
"ThumbnailSnapToGridSizeY": 97,
"ThumbnailSnapToGridSizeX": 128,
"ThumbnailSnapToGridSizeY": 72,
"EnableActiveClientHighlight": true,
"ActiveClientHighlightColor": "GreenYellow",
"OverlayLabelColor": "Orange",
"OverlayLabelSize": 10,
"EnableThumbnailRegionSnipping": true,
"DefaultThumbnailRegion": "1384, 188, 451, 388",
"EnableThumbnailRegionSnipping": false,
"DefaultThumbnailRegion": "1664, 188, 451, 238",
"CurrentProfile": "Default",
"AvailableProfiles": [
"Default"
@@ -110,19 +110,21 @@
"LoginThumbnailLocation": "5, 5",
"ToggleTrackingHotkey": "Alt+F16",
"ToggleSingleProcessHotkey": "Control+F16",
"ToggleAllThumbnailsHotkey": "Shift+Alt+Oem3",
"ThumbnailsManuallyHidden": true,
"ToggleAllThumbnailsHotkey": "Alt+Oem3",
"ThumbnailsManuallyHidden": false,
"PerClientLayout": {},
"FlatLayout": {
"EVE - Quartio": "-1229, 1067",
"EVE - Tertiale": "-1680, 1067",
"EVE - Secundamen": "-2131, 1067",
"EVE - Primorium": "-2576, 679",
"EVE - PhatPhuckDave": "-2576, 291"
"EVE - Quartio": "-2560, 1152",
"EVE - Tertiale": "-2048, 1152",
"EVE - PhatPhuckDave": "-512, 1152",
"EVE - Primorium": "-1024, 1152",
"EVE - Secundamen": "-1536, 1152"
},
"ClientLayout": {},
"ClientHotkey": {},
"DisableThumbnail": {},
"DisableThumbnail": {
"EVE - PhatPhuckDave (1)": false
},
"PriorityClients": [],
"ExecutablesToPreview": [
"exefile"

View File

@@ -0,0 +1,135 @@
{
"ConfigVersion": 1,
"CycleGroup1ForwardHotkeys": [
"F14",
"Control+F14"
],
"CycleGroup1BackwardHotkeys": [
"F13",
"Control+F13"
],
"CycleGroup1ClientsOrder": {
"EVE - Example DPS Toon 1": 1,
"EVE - Example DPS Toon 2": 2,
"EVE - Example DPS Toon 3": 3
},
"CycleGroup2ForwardHotkeys": [
"F16",
"Control+F16"
],
"CycleGroup2BackwardHotkeys": [
"F15",
"Control+F15"
],
"CycleGroup2ClientsOrder": {
"EVE - Example Logi Toon 1": 1,
"EVE - Example Scout Toon 2": 2,
"EVE - Example Tackle Toon 3": 3
},
"CycleGroup3ForwardHotkeys": [
""
],
"CycleGroup3BackwardHotkeys": [
""
],
"CycleGroup3ClientsOrder": {
"EVE - cycle group 3": 1
},
"CycleGroup4ForwardHotkeys": [
""
],
"CycleGroup4BackwardHotkeys": [
""
],
"CycleGroup4ClientsOrder": {
"EVE - cycle group 4": 1
},
"CycleGroup5ForwardHotkeys": [
""
],
"CycleGroup5BackwardHotkeys": [
""
],
"CycleGroup5ClientsOrder": {
"EVE - cycle group 5": 1
},
"PerClientActiveClientHighlightColor": {
"EVE - Example Toon 1": "Red",
"EVE - Example Toon 2": "Green"
},
"PerClientThumbnailSize": {
"EVE - Example Toon 1": "200, 200",
"EVE - Example Toon 2": "200, 200"
},
"PerClientThumbnailRegion": {},
"PerClientZoomAnchor": {
"EVE - Example Toon 1": 1,
"EVE - Example Toon 2": 7
},
"MinimizeToTray": true,
"ThumbnailRefreshPeriod": 500,
"ThumbnailResizeTimeoutPeriod": 500,
"WineCompatibilityMode": false,
"ThumbnailsOpacity": 1.0,
"EnableClientLayoutTracking": false,
"HideActiveClientThumbnail": false,
"HideLoginClientThumbnail": false,
"MinimizeInactiveClients": false,
"WindowsAnimationStyle": 1,
"ShowThumbnailsAlwaysOnTop": true,
"EnablePerClientThumbnailLayouts": false,
"HideThumbnailsOnLostFocus": false,
"HideThumbnailsDelay": 2,
"ThumbnailSize": "451, 238",
"ThumbnailMaximumSize": "960, 540",
"ThumbnailMinimumSize": "192, 108",
"EnableThumbnailSnap": true,
"ThumbnailSnapRange": 150,
"EnableThumbnailZoom": false,
"ThumbnailZoomFactor": 2,
"ThumbnailZoomAnchor": 0,
"OverlayLabelAnchor": 0,
"ShowThumbnailOverlays": true,
"ShowThumbnailFrames": false,
"LockThumbnailLocation": false,
"ThumbnailSnapToGrid": true,
"ThumbnailSnapToGridSizeX": 112,
"ThumbnailSnapToGridSizeY": 59,
"EnableActiveClientHighlight": true,
"ActiveClientHighlightColor": "GreenYellow",
"OverlayLabelColor": "Orange",
"OverlayLabelSize": 10,
"EnableThumbnailRegionSnipping": true,
"DefaultThumbnailRegion": "1664, 188, 451, 238",
"CurrentProfile": "Default",
"ProfileReadOnly": false,
"IconName": "IconOriginal",
"ActiveClientHighlightThickness": 3,
"LoginThumbnailLocation": "5, 5",
"ToggleTrackingHotkey": "Alt+F16",
"ToggleSingleProcessHotkey": "Control+F16",
"ToggleAllThumbnailsHotkey": "Shift+Alt+Oem3",
"ThumbnailsManuallyHidden": false,
"PerClientLayout": {},
"FlatLayout": {
"EVE - Sn v1 cosunoo (2)": "1995, 1058",
"EVE - Primorium (1)": "240, 645",
"EVE - PhatPhuckDave (3)": "224, -2",
"EVE - Primorium (3)": "146, 285",
"EVE - PhatPhuckDave (2)": "146, 57",
"EVE - Sn v1 cosunoo (1)": "154, 472",
"EVE - Sn v1 cosunoo (3)": "292, 517",
"EVE - Primorium (2)": "224, 236",
"EVE - PhatPhuckDave (1)": "292, 57",
"EVE - Secundamen (1)": "224, 474"
},
"ClientLayout": {},
"ClientHotkey": {},
"DisableThumbnail": {
"EVE - PhatPhuckDave (1)": false
},
"PriorityClients": [],
"ExecutablesToPreview": [
"exefile"
]
}

View File

@@ -0,0 +1,130 @@
{
"ConfigVersion": 1,
"CycleGroup1ForwardHotkeys": [
"F14",
"Control+F14"
],
"CycleGroup1BackwardHotkeys": [
"F13",
"Control+F13"
],
"CycleGroup1ClientsOrder": {
"EVE - Example DPS Toon 1": 1,
"EVE - Example DPS Toon 2": 2,
"EVE - Example DPS Toon 3": 3
},
"CycleGroup2ForwardHotkeys": [
"F16",
"Control+F16"
],
"CycleGroup2BackwardHotkeys": [
"F15",
"Control+F15"
],
"CycleGroup2ClientsOrder": {
"EVE - Example Logi Toon 1": 1,
"EVE - Example Scout Toon 2": 2,
"EVE - Example Tackle Toon 3": 3
},
"CycleGroup3ForwardHotkeys": [
""
],
"CycleGroup3BackwardHotkeys": [
""
],
"CycleGroup3ClientsOrder": {
"EVE - cycle group 3": 1
},
"CycleGroup4ForwardHotkeys": [
""
],
"CycleGroup4BackwardHotkeys": [
""
],
"CycleGroup4ClientsOrder": {
"EVE - cycle group 4": 1
},
"CycleGroup5ForwardHotkeys": [
""
],
"CycleGroup5BackwardHotkeys": [
""
],
"CycleGroup5ClientsOrder": {
"EVE - cycle group 5": 1
},
"PerClientActiveClientHighlightColor": {
"EVE - Example Toon 1": "Red",
"EVE - Example Toon 2": "Green"
},
"PerClientThumbnailSize": {
"EVE - Example Toon 1": "200, 200",
"EVE - Example Toon 2": "200, 200"
},
"PerClientThumbnailRegion": {},
"PerClientZoomAnchor": {
"EVE - Example Toon 1": 1,
"EVE - Example Toon 2": 7
},
"MinimizeToTray": true,
"ThumbnailRefreshPeriod": 500,
"ThumbnailResizeTimeoutPeriod": 500,
"WineCompatibilityMode": false,
"ThumbnailsOpacity": 1.0,
"EnableClientLayoutTracking": false,
"HideActiveClientThumbnail": false,
"HideLoginClientThumbnail": false,
"MinimizeInactiveClients": false,
"WindowsAnimationStyle": 1,
"ShowThumbnailsAlwaysOnTop": true,
"EnablePerClientThumbnailLayouts": false,
"HideThumbnailsOnLostFocus": false,
"HideThumbnailsDelay": 2,
"ThumbnailSize": "429, 140",
"ThumbnailMaximumSize": "960, 540",
"ThumbnailMinimumSize": "192, 108",
"EnableThumbnailSnap": true,
"ThumbnailSnapRange": 0,
"EnableThumbnailZoom": false,
"ThumbnailZoomFactor": 2,
"ThumbnailZoomAnchor": 0,
"OverlayLabelAnchor": 0,
"ShowThumbnailOverlays": true,
"ShowThumbnailFrames": false,
"LockThumbnailLocation": false,
"ThumbnailSnapToGrid": true,
"ThumbnailSnapToGridSizeX": 107,
"ThumbnailSnapToGridSizeY": 35,
"EnableActiveClientHighlight": true,
"ActiveClientHighlightColor": "GreenYellow",
"OverlayLabelColor": "Orange",
"OverlayLabelSize": 10,
"EnableThumbnailRegionSnipping": true,
"DefaultThumbnailRegion": "1205, 1269, 429, 140",
"CurrentProfile": "Default",
"AvailableProfiles": [
"Default"
],
"IconName": "IconOriginal",
"ActiveClientHighlightThickness": 3,
"LoginThumbnailLocation": "5, 5",
"ToggleTrackingHotkey": "Alt+F16",
"ToggleSingleProcessHotkey": "Control+F16",
"ToggleAllThumbnailsHotkey": "Alt+Oem3",
"ThumbnailsManuallyHidden": false,
"PerClientLayout": {},
"FlatLayout": {
"EVE - Quartio": "0, 1295",
"EVE - Tertiale": "0, 1155",
"EVE - Secundamen": "0, 1015",
"EVE - Primorium": "0, 875",
"EVE - PhatPhuckDave": "0, 735"
},
"ClientLayout": {},
"ClientHotkey": {},
"DisableThumbnail": {},
"PriorityClients": [],
"ExecutablesToPreview": [
"exefile"
]
}

View File

@@ -0,0 +1,130 @@
{
"ConfigVersion": 1,
"CycleGroup1ForwardHotkeys": [
"F14",
"Control+F14"
],
"CycleGroup1BackwardHotkeys": [
"F13",
"Control+F13"
],
"CycleGroup1ClientsOrder": {
"EVE - Example DPS Toon 1": 1,
"EVE - Example DPS Toon 2": 2,
"EVE - Example DPS Toon 3": 3
},
"CycleGroup2ForwardHotkeys": [
"F16",
"Control+F16"
],
"CycleGroup2BackwardHotkeys": [
"F15",
"Control+F15"
],
"CycleGroup2ClientsOrder": {
"EVE - Example Logi Toon 1": 1,
"EVE - Example Scout Toon 2": 2,
"EVE - Example Tackle Toon 3": 3
},
"CycleGroup3ForwardHotkeys": [
""
],
"CycleGroup3BackwardHotkeys": [
""
],
"CycleGroup3ClientsOrder": {
"EVE - cycle group 3": 1
},
"CycleGroup4ForwardHotkeys": [
""
],
"CycleGroup4BackwardHotkeys": [
""
],
"CycleGroup4ClientsOrder": {
"EVE - cycle group 4": 1
},
"CycleGroup5ForwardHotkeys": [
""
],
"CycleGroup5BackwardHotkeys": [
""
],
"CycleGroup5ClientsOrder": {
"EVE - cycle group 5": 1
},
"PerClientActiveClientHighlightColor": {
"EVE - Example Toon 1": "Red",
"EVE - Example Toon 2": "Green"
},
"PerClientThumbnailSize": {
"EVE - Example Toon 1": "200, 200",
"EVE - Example Toon 2": "200, 200"
},
"PerClientThumbnailRegion": {},
"PerClientZoomAnchor": {
"EVE - Example Toon 1": 1,
"EVE - Example Toon 2": 7
},
"MinimizeToTray": true,
"ThumbnailRefreshPeriod": 500,
"ThumbnailResizeTimeoutPeriod": 500,
"WineCompatibilityMode": false,
"ThumbnailsOpacity": 1.0,
"EnableClientLayoutTracking": false,
"HideActiveClientThumbnail": false,
"HideLoginClientThumbnail": false,
"MinimizeInactiveClients": false,
"WindowsAnimationStyle": 1,
"ShowThumbnailsAlwaysOnTop": true,
"EnablePerClientThumbnailLayouts": false,
"HideThumbnailsOnLostFocus": false,
"HideThumbnailsDelay": 2,
"ThumbnailSize": "451, 238",
"ThumbnailMaximumSize": "960, 540",
"ThumbnailMinimumSize": "192, 108",
"EnableThumbnailSnap": true,
"ThumbnailSnapRange": 0,
"EnableThumbnailZoom": false,
"ThumbnailZoomFactor": 2,
"ThumbnailZoomAnchor": 0,
"OverlayLabelAnchor": 0,
"ShowThumbnailOverlays": true,
"ShowThumbnailFrames": false,
"LockThumbnailLocation": false,
"ThumbnailSnapToGrid": true,
"ThumbnailSnapToGridSizeX": 112,
"ThumbnailSnapToGridSizeY": 59,
"EnableActiveClientHighlight": true,
"ActiveClientHighlightColor": "GreenYellow",
"OverlayLabelColor": "Orange",
"OverlayLabelSize": 10,
"EnableThumbnailRegionSnipping": true,
"DefaultThumbnailRegion": "1384, 188, 451, 238",
"CurrentProfile": "Default",
"AvailableProfiles": [
"Default"
],
"IconName": "IconOriginal",
"ActiveClientHighlightThickness": 3,
"LoginThumbnailLocation": "5, 5",
"ToggleTrackingHotkey": "Alt+F16",
"ToggleSingleProcessHotkey": "Control+F16",
"ToggleAllThumbnailsHotkey": "Alt+Oem3",
"ThumbnailsManuallyHidden": false,
"PerClientLayout": {},
"FlatLayout": {
"EVE - Quartio": "448, 1239",
"EVE - Tertiale": "448, 1003",
"EVE - Secundamen": "0, 1239",
"EVE - Primorium": "0, 1003",
"EVE - PhatPhuckDave": "0, 767"
},
"ClientLayout": {},
"ClientHotkey": {},
"DisableThumbnail": {},
"PriorityClients": [],
"ExecutablesToPreview": [
"exefile"
]
}

View File

@@ -0,0 +1,130 @@
{
"ConfigVersion": 1,
"CycleGroup1ForwardHotkeys": [
"F14",
"Control+F14"
],
"CycleGroup1BackwardHotkeys": [
"F13",
"Control+F13"
],
"CycleGroup1ClientsOrder": {
"EVE - Example DPS Toon 1": 1,
"EVE - Example DPS Toon 2": 2,
"EVE - Example DPS Toon 3": 3
},
"CycleGroup2ForwardHotkeys": [
"F16",
"Control+F16"
],
"CycleGroup2BackwardHotkeys": [
"F15",
"Control+F15"
],
"CycleGroup2ClientsOrder": {
"EVE - Example Logi Toon 1": 1,
"EVE - Example Scout Toon 2": 2,
"EVE - Example Tackle Toon 3": 3
},
"CycleGroup3ForwardHotkeys": [
""
],
"CycleGroup3BackwardHotkeys": [
""
],
"CycleGroup3ClientsOrder": {
"EVE - cycle group 3": 1
},
"CycleGroup4ForwardHotkeys": [
""
],
"CycleGroup4BackwardHotkeys": [
""
],
"CycleGroup4ClientsOrder": {
"EVE - cycle group 4": 1
},
"CycleGroup5ForwardHotkeys": [
""
],
"CycleGroup5BackwardHotkeys": [
""
],
"CycleGroup5ClientsOrder": {
"EVE - cycle group 5": 1
},
"PerClientActiveClientHighlightColor": {
"EVE - Example Toon 1": "Red",
"EVE - Example Toon 2": "Green"
},
"PerClientThumbnailSize": {
"EVE - Example Toon 1": "200, 200",
"EVE - Example Toon 2": "200, 200"
},
"PerClientThumbnailRegion": {},
"PerClientZoomAnchor": {
"EVE - Example Toon 1": 1,
"EVE - Example Toon 2": 7
},
"MinimizeToTray": true,
"ThumbnailRefreshPeriod": 500,
"ThumbnailResizeTimeoutPeriod": 500,
"WineCompatibilityMode": false,
"ThumbnailsOpacity": 1.0,
"EnableClientLayoutTracking": false,
"HideActiveClientThumbnail": false,
"HideLoginClientThumbnail": false,
"MinimizeInactiveClients": false,
"WindowsAnimationStyle": 1,
"ShowThumbnailsAlwaysOnTop": true,
"EnablePerClientThumbnailLayouts": false,
"HideThumbnailsOnLostFocus": false,
"HideThumbnailsDelay": 2,
"ThumbnailSize": "451, 388",
"ThumbnailMaximumSize": "960, 540",
"ThumbnailMinimumSize": "192, 108",
"EnableThumbnailSnap": true,
"ThumbnailSnapRange": 0,
"EnableThumbnailZoom": false,
"ThumbnailZoomFactor": 2,
"ThumbnailZoomAnchor": 0,
"OverlayLabelAnchor": 0,
"ShowThumbnailOverlays": true,
"ShowThumbnailFrames": false,
"LockThumbnailLocation": false,
"ThumbnailSnapToGrid": true,
"ThumbnailSnapToGridSizeX": 112,
"ThumbnailSnapToGridSizeY": 97,
"EnableActiveClientHighlight": true,
"ActiveClientHighlightColor": "GreenYellow",
"OverlayLabelColor": "Orange",
"OverlayLabelSize": 10,
"EnableThumbnailRegionSnipping": true,
"DefaultThumbnailRegion": "1384, 188, 451, 388",
"CurrentProfile": "Default",
"AvailableProfiles": [
"Default"
],
"IconName": "IconOriginal",
"ActiveClientHighlightThickness": 3,
"LoginThumbnailLocation": "5, 5",
"ToggleTrackingHotkey": "Alt+F16",
"ToggleSingleProcessHotkey": "Control+F16",
"ToggleAllThumbnailsHotkey": "Alt+Oem3",
"ThumbnailsManuallyHidden": true,
"PerClientLayout": {},
"FlatLayout": {
"EVE - Quartio": "-1120, 1067",
"EVE - Tertiale": "-1568, 1067",
"EVE - Secundamen": "-2016, 1067",
"EVE - Primorium": "-2464, 679",
"EVE - PhatPhuckDave": "-2464, 291"
},
"ClientLayout": {},
"ClientHotkey": {},
"DisableThumbnail": {},
"PriorityClients": [],
"ExecutablesToPreview": [
"exefile"
]
}

View File

@@ -1,16 +1,32 @@
using System.IO;
using System;
using System.IO;
using Newtonsoft.Json;
namespace EveOPreview.Configuration.Implementation {
class ConfigurationStorage : IConfigurationStorage {
private const string CONFIGURATION_FILE_NAME = "EVE-O-Preview.json";
private const string PROFILES_FOLDER_NAME = "Profiles";
private const string PROFILE_CONFIG_FILE_EXTENSION = ".json";
private readonly IAppConfig _appConfig;
private readonly IThumbnailConfiguration _thumbnailConfiguration;
private readonly string _baseDirectory;
private string _currentProfile;
public ConfigurationStorage(IAppConfig appConfig, IThumbnailConfiguration thumbnailConfiguration) {
this._appConfig = appConfig;
this._thumbnailConfiguration = thumbnailConfiguration;
this._baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
this._currentProfile = "Default";
}
public string CurrentProfile {
get => this._currentProfile;
set {
if (this._currentProfile != value) {
this._currentProfile = value ?? "Default";
}
}
}
public void Load() {
@@ -38,6 +54,12 @@ namespace EveOPreview.Configuration.Implementation {
string filename = this.GetConfigFileName();
try {
// Ensure the directory exists before saving
string directory = Path.GetDirectoryName(filename);
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) {
Directory.CreateDirectory(directory);
}
File.WriteAllText(filename, rawData);
} catch (IOException) {
// Ignore error if for some reason the updated config cannot be written down
@@ -45,8 +67,19 @@ namespace EveOPreview.Configuration.Implementation {
}
private string GetConfigFileName() {
return string.IsNullOrEmpty(this._appConfig.ConfigFileName) ? ConfigurationStorage.CONFIGURATION_FILE_NAME
: this._appConfig.ConfigFileName;
// If a custom config file is specified via command line, use it
if (!string.IsNullOrEmpty(this._appConfig.ConfigFileName)) {
return this._appConfig.ConfigFileName;
}
// If using the Default profile or no profile is set, use the main config file
if (string.IsNullOrEmpty(this._currentProfile) || this._currentProfile == "Default") {
return Path.Combine(this._baseDirectory, CONFIGURATION_FILE_NAME);
}
// For named profiles, use the profile-specific config file in the Profiles folder
string profilesFolder = Path.Combine(this._baseDirectory, PROFILES_FOLDER_NAME);
return Path.Combine(profilesFolder, this._currentProfile + PROFILE_CONFIG_FILE_EXTENSION);
}
}
}

View File

@@ -0,0 +1,136 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using Newtonsoft.Json;
namespace EveOPreview.Configuration.Implementation {
class ProfileManager : IProfileManager {
private const string PROFILES_FOLDER_NAME = "Profiles";
private const string MASTER_CONFIG_FILE_NAME = "EVE-O-Preview-Master.json";
private const string PROFILE_CONFIG_FILE_EXTENSION = ".json";
private readonly IAppConfig _appConfig;
private readonly IConfigurationStorage _configurationStorage;
private readonly string _baseDirectory;
public ProfileManager(IAppConfig appConfig, IConfigurationStorage configurationStorage) {
this._appConfig = appConfig;
this._configurationStorage = configurationStorage;
// Get the base directory (where the main config file is located)
// We'll use the application base directory
this._baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
// Ensure Profiles folder exists
this.EnsureProfilesFolderExists();
// Ensure master config exists
this.EnsureMasterConfigExists();
}
public System.Collections.Generic.List<string> GetAvailableProfiles() {
string profilesPath = this.GetProfilesFolderPath();
var profiles = new System.Collections.Generic.List<string> { "Default" };
if (Directory.Exists(profilesPath)) {
var profileFiles = Directory.GetFiles(profilesPath, "*" + PROFILE_CONFIG_FILE_EXTENSION);
foreach (var file in profileFiles) {
string profileName = Path.GetFileNameWithoutExtension(file);
if (!string.IsNullOrEmpty(profileName) && !profiles.Contains(profileName)) {
profiles.Add(profileName);
}
}
}
return profiles;
}
public string GetActiveProfile() {
string masterConfigPath = this.GetMasterConfigPath();
if (!File.Exists(masterConfigPath)) {
return "Default";
}
try {
string rawData = File.ReadAllText(masterConfigPath);
var masterConfig = JsonConvert.DeserializeObject<MasterConfig>(rawData);
return masterConfig?.ActiveProfile ?? "Default";
} catch {
return "Default";
}
}
public void SwitchProfile(string profileName) {
if (string.IsNullOrEmpty(profileName)) {
profileName = "Default";
}
// Save current configuration first
this._configurationStorage.Save();
// Update master config with new profile
this.SaveActiveProfile(profileName);
// Restart the application
this.RestartApplication();
}
public string GetProfileConfigPath(string profileName) {
if (string.IsNullOrEmpty(profileName) || profileName == "Default") {
return null;
}
return Path.Combine(this.GetProfilesFolderPath(), profileName + PROFILE_CONFIG_FILE_EXTENSION);
}
private string GetProfilesFolderPath() {
return Path.Combine(this._baseDirectory, PROFILES_FOLDER_NAME);
}
private string GetMasterConfigPath() {
return Path.Combine(this._baseDirectory, MASTER_CONFIG_FILE_NAME);
}
private void EnsureProfilesFolderExists() {
string profilesPath = this.GetProfilesFolderPath();
if (!Directory.Exists(profilesPath)) {
Directory.CreateDirectory(profilesPath);
}
}
private void EnsureMasterConfigExists() {
string masterConfigPath = this.GetMasterConfigPath();
if (!File.Exists(masterConfigPath)) {
var defaultConfig = new MasterConfig { ActiveProfile = "Default" };
string rawData = JsonConvert.SerializeObject(defaultConfig, Formatting.Indented);
File.WriteAllText(masterConfigPath, rawData);
}
}
private void SaveActiveProfile(string profileName) {
var masterConfig = new MasterConfig { ActiveProfile = profileName };
string rawData = JsonConvert.SerializeObject(masterConfig, Formatting.Indented);
string masterConfigPath = this.GetMasterConfigPath();
try {
File.WriteAllText(masterConfigPath, rawData);
} catch (IOException) {
// Ignore error if config cannot be written
}
}
private void RestartApplication() {
// Call the static method in Program which properly handles the mutex
Program.RestartApplication();
}
private class MasterConfig {
public string ActiveProfile { get; set; }
}
}
}

View File

@@ -0,0 +1,25 @@
using System.Collections.Generic;
namespace EveOPreview.Configuration {
public interface IProfileManager {
/// <summary>
/// Gets the list of available profile names from the Profiles folder
/// </summary>
List<string> GetAvailableProfiles();
/// <summary>
/// Gets the currently active profile name from the master config
/// </summary>
string GetActiveProfile();
/// <summary>
/// Switches to the specified profile, saves current config, updates master config, and restarts the application
/// </summary>
void SwitchProfile(string profileName);
/// <summary>
/// Gets the full path to a profile's config file
/// </summary>
string GetProfileConfigPath(string profileName);
}
}

View File

@@ -18,6 +18,7 @@ namespace EveOPreview.Presenters {
private readonly IMediator _mediator;
private readonly IThumbnailConfiguration _configuration;
private readonly IConfigurationStorage _configurationStorage;
private readonly IProfileManager _profileManager;
private readonly IDictionary<string, IThumbnailDescription> _descriptionsCache;
private bool _suppressSizeNotifications;
@@ -25,11 +26,13 @@ namespace EveOPreview.Presenters {
#endregion
public MainFormPresenter(IApplicationController controller, IMainFormView view, IMediator mediator,
IThumbnailConfiguration configuration, IConfigurationStorage configurationStorage)
IThumbnailConfiguration configuration, IConfigurationStorage configurationStorage,
IProfileManager profileManager)
: base(controller, view) {
this._mediator = mediator;
this._configuration = configuration;
this._configurationStorage = configurationStorage;
this._profileManager = profileManager;
this._descriptionsCache = new Dictionary<string, IThumbnailDescription>();
@@ -44,6 +47,7 @@ namespace EveOPreview.Presenters {
this.View.ThumbnailStateChanged = this.UpdateThumbnailState;
this.View.DocumentationLinkActivated = this.OpenDocumentationLink;
this.View.ApplicationExitRequested = this.ExitApplication;
this.View.ProfileSwitchRequested = this.SwitchProfile;
this.View.IconName = this._configuration.IconName;
}
@@ -57,10 +61,23 @@ namespace EveOPreview.Presenters {
this.View.Minimize();
}
// Initialize the tray profile menu
this.UpdateTrayProfileMenu();
this._mediator.Send(new StartService());
this._suppressSizeNotifications = false;
}
private void UpdateTrayProfileMenu() {
var profiles = this._profileManager.GetAvailableProfiles();
var currentProfile = this._profileManager.GetActiveProfile();
this.View.UpdateTrayProfileMenu(profiles, currentProfile);
}
private void SwitchProfile(string profileName) {
this._profileManager.SwitchProfile(profileName);
}
private void Minimize() {
if (!this._configuration.MinimizeToTray) {
return;

View File

@@ -2,6 +2,7 @@ using System;
using System.Threading;
using System.Windows.Forms;
using EveOPreview.Configuration;
using EveOPreview.Configuration.Implementation;
using EveOPreview.Presenters;
using EveOPreview.Services;
using EveOPreview.View;
@@ -78,9 +79,13 @@ namespace EveOPreview {
container.Register(typeof(IRequestHandler<, >), typeof(Program).Assembly);
// Configuration services
container.Register<IConfigurationStorage>();
container.Register<IAppConfig>();
container.Register<IThumbnailConfiguration>();
container.Register<IConfigurationStorage>();
container.Register<IProfileManager>();
// Initialize profile system
Program.InitializeProfileSystem(container);
// Application services
container.Register<IThumbnailManager>();
@@ -98,5 +103,49 @@ namespace EveOPreview {
return controller;
}
private static void InitializeProfileSystem(IIocContainer container) {
var profileManager = container.Resolve<IProfileManager>();
var configurationStorage = container.Resolve<IConfigurationStorage>();
var thumbnailConfiguration = container.Resolve<IThumbnailConfiguration>();
// Get the active profile from master config
string activeProfile = profileManager.GetActiveProfile();
// Set the current profile in the configuration storage
if (configurationStorage is ConfigurationStorage configStorage) {
configStorage.CurrentProfile = activeProfile;
}
// Update the thumbnail configuration with the active profile
thumbnailConfiguration.CurrentProfile = activeProfile;
thumbnailConfiguration.AvailableProfiles = profileManager.GetAvailableProfiles();
}
public static void RestartApplication() {
// Get the current executable path
string executablePath = System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName;
if (string.IsNullOrEmpty(executablePath)) {
return;
}
// Release the mutex first so the new instance can start
Program._singleInstanceMutex?.Dispose();
Program._singleInstanceMutex = null;
// Start a new instance of the application
try {
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo {
FileName = executablePath,
UseShellExecute = true
});
} catch (Exception) {
// If starting the new process fails, we're in a bad state
// Just exit anyway
}
// Exit the current application immediately
Environment.Exit(0);
}
}
}

View File

@@ -177,6 +177,8 @@ namespace EveOPreview.Services {
this._toggleAllThumbnailsHotkey = new HotkeyHandler(mainHandle, toggleAllThumbnailsKey);
this._toggleAllThumbnailsHotkey.Pressed += (object s, HandledEventArgs e) => {
this._configuration.ThumbnailsManuallyHidden = !this._configuration.ThumbnailsManuallyHidden;
this._hideThumbnailsDelay = 0;
this.RefreshThumbnails();
System.Diagnostics.Debug.WriteLine(
$"Toggled all thumbnails: {(this._configuration.ThumbnailsManuallyHidden ? "Hidden" : "Visible")}");
e.Handled = true;
@@ -256,6 +258,8 @@ namespace EveOPreview.Services {
this._toggleAllThumbnailsHotkey = new HotkeyHandler(mainHandle, toggleAllThumbnailsKey);
this._toggleAllThumbnailsHotkey.Pressed += (object s, HandledEventArgs e) => {
this._configuration.ThumbnailsManuallyHidden = !this._configuration.ThumbnailsManuallyHidden;
this._hideThumbnailsDelay = 0;
this.RefreshThumbnails();
System.Diagnostics.Debug.WriteLine(
$"Toggled all thumbnails: {(this._configuration.ThumbnailsManuallyHidden ? "Hidden" : "Visible")}");
e.Handled = true;

View File

@@ -419,6 +419,71 @@ namespace EveOPreview.View {
public Action DocumentationLinkActivated { get; set; }
public Action<string> ProfileSwitchRequested { get; set; }
public void UpdateTrayProfileMenu(List<string> profiles, string currentProfile) {
// Clear existing items from the tray menu
this.TrayMenu.Items.Clear();
// Add title
ToolStripMenuItem titleMenuItem = new ToolStripMenuItem();
titleMenuItem.Enabled = false;
titleMenuItem.Name = "TitleMenuItem";
titleMenuItem.Size = new System.Drawing.Size(200, 22);
titleMenuItem.Text = "EVE-O-Preview";
this.TrayMenu.Items.Add(titleMenuItem);
// Add restore option
ToolStripMenuItem restoreMenuItem = new ToolStripMenuItem();
restoreMenuItem.Name = "RestoreWindowMenuItem";
restoreMenuItem.Size = new System.Drawing.Size(200, 22);
restoreMenuItem.Text = "Restore";
restoreMenuItem.Click += this.RestoreMainForm_Handler;
this.TrayMenu.Items.Add(restoreMenuItem);
// Add separator
ToolStripSeparator separatorMenuItem = new ToolStripSeparator();
separatorMenuItem.Name = "SeparatorMenuItem";
separatorMenuItem.Size = new System.Drawing.Size(200, 6);
this.TrayMenu.Items.Add(separatorMenuItem);
// Add profile submenu
ToolStripMenuItem profileMenuItem = new ToolStripMenuItem();
profileMenuItem.Name = "ProfileMenuItem";
profileMenuItem.Size = new System.Drawing.Size(200, 22);
profileMenuItem.Text = "Profiles";
foreach (var profile in profiles) {
ToolStripMenuItem profileItem = new ToolStripMenuItem();
profileItem.Name = "Profile_" + profile;
profileItem.Size = new System.Drawing.Size(180, 22);
profileItem.Text = profile;
profileItem.Checked = (profile == currentProfile);
profileItem.Click += (sender, e) => {
this.ProfileSwitchRequested?.Invoke(profile);
};
profileMenuItem.DropDownItems.Add(profileItem);
}
this.TrayMenu.Items.Add(profileMenuItem);
// Add final separator
ToolStripSeparator finalSeparatorMenuItem = new ToolStripSeparator();
finalSeparatorMenuItem.Name = "FinalSeparatorMenuItem";
finalSeparatorMenuItem.Size = new System.Drawing.Size(200, 6);
this.TrayMenu.Items.Add(finalSeparatorMenuItem);
// Add exit option
ToolStripMenuItem exitMenuItem = new ToolStripMenuItem();
exitMenuItem.Name = "ExitMenuItem";
exitMenuItem.Size = new System.Drawing.Size(200, 22);
exitMenuItem.Text = "Exit";
exitMenuItem.Click += this.ExitMenuItemClick_Handler;
this.TrayMenu.Items.Add(exitMenuItem);
}
#region UI events
private void ContentTabControl_DrawItem(object sender, DrawItemEventArgs e) {
TabControl control = (TabControl)sender;

View File

@@ -63,6 +63,9 @@ namespace EveOPreview.View {
void RemoveThumbnails(IList<IThumbnailDescription> thumbnails);
void RefreshZoomSettings();
void UpdateTrayProfileMenu(List<string> profiles, string currentProfile);
Action<string> ProfileSwitchRequested { get; set; }
Action ApplicationExitRequested { get; set; }
Action FormActivated { get; set; }
Action FormMinimized { get; set; }